texlive[45832] Master/texmf-dist: exam (16nov17)
commits+karl at tug.org
commits+karl at tug.org
Thu Nov 16 23:14:35 CET 2017
Revision: 45832
http://tug.org/svn/texlive?view=revision&revision=45832
Author: karl
Date: 2017-11-16 23:14:35 +0100 (Thu, 16 Nov 2017)
Log Message:
-----------
exam (16nov17)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/exam/README
trunk/Master/texmf-dist/doc/latex/exam/exam.md5
trunk/Master/texmf-dist/doc/latex/exam/examdoc.pdf
trunk/Master/texmf-dist/doc/latex/exam/examdoc.tex
trunk/Master/texmf-dist/tex/latex/exam/exam.cls
Modified: trunk/Master/texmf-dist/doc/latex/exam/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exam/README 2017-11-16 22:14:19 UTC (rev 45831)
+++ trunk/Master/texmf-dist/doc/latex/exam/README 2017-11-16 22:14:35 UTC (rev 45832)
@@ -1,4 +1,5 @@
-This is version 2.5 of the exam document class, dated May 7, 2015.
+This is version 2.6 of the exam document class, dated October 26,
+2017.
The exam document class, together with its user's guide examdoc.tex,
attempts to make it easy for even a LaTeX novice to prepare exams.
@@ -11,7 +12,8 @@
each question and the total possible points for that question) or by
page number (listing each page with points and the total possible
points for that page). A grading table can cover the entire exam or
-just a part of the exam.
+just a part of the exam. Grading tables can have multiple rows or
+multiple columns.
3. Create headers and footers that are each specified in three parts:
One part to be left justified, one part to be centered, and one part
@@ -38,9 +40,8 @@
e.g., point values, or table headings), so that they can be adapted to
personal taste and/or languages other than English.
-
The user's guide examdoc.tex attempts to explain all of the
-possibilities in a readable way, with many specific examples.
+possibilities in a readable way, with many examples.
--------------------------------------------------------------------
Modified: trunk/Master/texmf-dist/doc/latex/exam/exam.md5
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exam/exam.md5 2017-11-16 22:14:19 UTC (rev 45831)
+++ trunk/Master/texmf-dist/doc/latex/exam/exam.md5 2017-11-16 22:14:35 UTC (rev 45832)
@@ -1,3 +1,3 @@
-3d7b2787a32cf31f94fce30dbebe6a6d exam.cls
-0b79dabd1e74952a1f70abe1909330c2 examdoc.tex
-6c10f29d36dd8e009e854721b391fb50 examdoc.pdf
+01d4eea329c471b4295296dff587c23a exam.cls
+831e1841882d3e05abdae653595862d6 examdoc.pdf
+a9a481f4f36ec3dbf90ffe63f57ce803 examdoc.tex
Modified: trunk/Master/texmf-dist/doc/latex/exam/examdoc.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/exam/examdoc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exam/examdoc.tex 2017-11-16 22:14:19 UTC (rev 45831)
+++ trunk/Master/texmf-dist/doc/latex/exam/examdoc.tex 2017-11-16 22:14:35 UTC (rev 45832)
@@ -8,7 +8,8 @@
% The exam documentclass itself is in the file exam.cls.
-%%% Copyright (c) 1997, 2000, 2004, 2008, 2011, 2015 Philip S. Hirschhorn
+%%% Copyright (c) 1997, 2000, 2004, 2008, 2011, 2015, 2017
+% Philip S. Hirschhorn
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
@@ -49,9 +50,9 @@
% without generating pdf warnings:
\newcommand{\bs}{\texorpdfstring{\char`\\}{}}
-\newcommand{\docversion}{2.5}
-\newcommand{\docdate}{May 7, 2015}
-%\newcommand{\docdate}{\today}
+\newcommand{\docversion}{2.6}
+\newcommand{\docdate}{November 5, 2017}
+%\newcommand{\docdate}{Draft: \today}
%--------------------------------------------------------------------
%
@@ -128,8 +129,8 @@
Wellesley College\\
Wellesley, MA 02481\\
psh at math.mit.edu\\[\bigskipamount]
- Copyright \copyright~1994, 1997, 2000, 2004, 2008, 2011, 2015 Philip
- Hirschhorn\\
+ Copyright \copyright~1994, 1997, 2000, 2004, 2008, 2011, 2015, 2017\\
+ Philip Hirschhorn\\
All rights reserved}
\date{\docdate}
@@ -509,8 +510,8 @@
space allocated by \verb"\vspace{\stretch{1}}".)
In addition to leaving blank space, it's also possible to leave lined
-space, dotted lined space, or an empty box. For the full story, see
-section~\ref{sec:LeaveSpace}.
+space, dotted lined space, space printed with a grid, or an empty box.
+For the full story, see section~\ref{sec:LeaveSpace}.
%--------------------------------------------------------------------
\subsection{Headers and footers}
@@ -687,19 +688,24 @@
of the exam (see section~\ref{sec:solutions}). The effect of this is
that
\begin{itemize}
-\item the contents of the
- environments\indt{solution}\indt{solutionorbox}%
- \indt{solutionorlines}\indt{solutionordottedlines}
+\item the contents of the environments
+ %
+ \index{solution environment@\texttt{solution} environment}%
+ %
+ \indt{solutionorbox}%
+ \indt{solutionorlines}\indt{solutionordottedlines}%
+ \indt{solutionorgrid}\indt{solutionbox}
\begin{center}
\begin{tabular}{l}
\verb"solution",\\
\verb"solutionorbox",\\
- \verb"solutionorlines", and\\
- \verb"solutionordottedlines"
+ \verb"solutionorlines",\\
+ \verb"solutionordottedlines",\\
+ \verb"solutionorgrid", and\\
+ \verb"solutionbox"
\end{tabular}
\end{center}
- (see section~\ref{sec:solutions}) will be printed on the next run of
- \LaTeX,
+ (see section~\ref{sec:solutions}) will be printed,
\item any choices of a \texttt{choices}\indt{choices},
\texttt{oneparchoices}\indt{oneparchoices},
\texttt{checkboxes}\indt{checkboxes}, or
@@ -1072,11 +1078,27 @@
of the question (or part, or subpart, or subsubpart) in parentheses,
but
\begin{itemize}
-\item the command \verb"\pointsinmargin"\indc{pointsinmargin} will
- cause the point values to be set in the left margin,
+\item the command \verb"\pointsinmargin"\indc{pointsinmargin} (or,
+ equivalently, the command
+ \verb"\pointsinleftmargin"\indc{pointsinleftmargin}) will cause the
+ point values to be set in the left margin,
\item the command
\verb"\pointsinrightmargin"\indc{pointsinrightmargin} will cause the
- point values to be set in the right margin, and
+ point values to be set in the right margin,
+\item the command
+ \verb"\pointstwosided"\indc{pointstwosided} will cause the
+ point values to be set
+ \begin{itemize}
+ \item in the right margin on odd numbered pages and
+ \item in the left margin on even numbered pages,
+ \end{itemize}
+\item the command
+ \verb"\pointstwosidedreversed"\indc{pointstwosidedreversed} will
+ cause the point values to be set
+ \begin{itemize}
+ \item in the left margin on odd numbered pages and
+ \item in the right margin on even numbered pages, and
+ \end{itemize}
\item the commands \verb"\nopointsinmargin"\indc{nopointsinmargin} and
\verb"\nopointsinrightmargin"\indc{nopointsinrightmargin} are
equivalent, and either of them will revert to the default situation.
@@ -1131,8 +1153,9 @@
section~\ref{sec:pointname}.)
\bigskip If you give the command
-\verb"\pointsinmargin"\indc{pointsinmargin}, then the above input will
-produce instead \pointsinmargin
+\verb"\pointsinmargin"\indc{pointsinmargin} (or, equivalently,
+\verb"\pointsinleftmargin"\indc{pointsinleftmargin}), then the above input
+will produce instead \pointsinmargin
\begin{questions}
\question[20]
Why is there air?
@@ -1489,8 +1512,9 @@
If you want some text (e.g., `` points'', or ``\%'') automatically
inserted along with the point values when using either
-\verb"\pointsinmargin" or \verb"\pointsinrightmargin", see the command
-\verb"\marginpointname" in section~\ref{sec:pointname}.
+\verb"\pointsinmargin", \verb"\pointsinrightmargin",
+\verb"\pointstwosided", or \verb"\pointstwosidedreversed", see the
+command \verb"\marginpointname" in section~\ref{sec:pointname}.
@@ -3611,7 +3635,8 @@
\index{customization!multiple choice questions|)}
%--------------------------------------------------------------------
%--------------------------------------------------------------------
-\section{Escaping the indentation: \texttt{\bs uplevel} and \texttt{\bs fullwidth}}
+\section{Escaping the indentation: \texttt{\bs uplevel} and
+ \texttt{\bs fullwidth}}
\label{sec:uplevel}
\index{indentation|(}
@@ -3708,9 +3733,9 @@
\end{verbatim}
by
\begin{verbatim}
- \begin{uplevel}
+ \begin{EnvUplevel}
The following two parts should be answered in classical Greek:
- \end{uplevel}
+ \end{EnvUplevel}
\end{verbatim}
If you want to give instructions for a group of questions, then the
@@ -4081,7 +4106,10 @@
that of the current line. That is, the left edge is at the current
left margin (which depends on whether we're in a question, part,
subpart, or subsubpart) and the right edge is at the right margin.
+(The box printed by the \verb"\makeemptybox" command can be printed in
+color; for that, see section~\ref{sec:colorboxes}.)
+
\medskip
For example, if you type
@@ -4157,6 +4185,7 @@
by including an optional argument with the \verb"solutionoremptybox"
environment; see section~\ref{sec:SolSpace}.
+
\indcstop{makeemptybox}
\index{empty box|)}
\index{space!empty box|)}
@@ -4178,6 +4207,24 @@
from the current left margin (which depends on whether we're in a
question, part, subpart, or subsubpart) to the right margin.
+By default, the lines are in black. However, if you give the
+commands\indc{colorfillwithlines}\index{color package}
+\begin{center}
+ \begin{tabular}{l}
+ \verb"\usepackage{color}"\\
+ \verb"\colorfillwithlines"
+ \end{tabular}
+\end{center}
+then the lines will be in color, by default a light gray. That
+default color was defined by the
+command\indc{definecolor}\indt{FillWithLinesColor}
+\begin{center}
+ \verb"\definecolor{FillWithLinesColor}{gray}{0.8}"
+\end{center}
+\index{customization!\texttt{\char`\\fillwithlines}} You can change
+the color by giving a new \verb"\definecolor" command to redefine the
+color \texttt{FillWithLinesColor}.
+
\medskip
For example, if you type
@@ -4301,6 +4348,26 @@
and that value can be changed by giving a new \verb"\setlength"
command.
+By default, the dotted lines are in black. However, if you give the
+commands\indc{colorfillwithdottedlines}\index{color package}
+\begin{center}
+ \begin{tabular}{l}
+ \verb"\usepackage{color}"\\
+ \verb"\colorfillwithdottedlines"
+ \end{tabular}
+\end{center}
+then the dotted lines will be in color, by default a light gray. That
+default color was defined by the
+command\indc{definecolor}\indt{FillWithDottedLinesColor}
+\begin{center}
+ \verb"\definecolor{FillWithDottedLinesColor}{gray}{0.8}"
+\end{center}
+\index{customization!\texttt{\char`\\fillwithdottedlines}} You can
+change the color by giving a new \verb"\definecolor" command to
+redefine the color \texttt{FillWithDottedLinesColor}.
+
+\medskip
+
For example, if you type
\begin{verbatim}
\begin{questions}
@@ -4412,7 +4479,7 @@
\verb"\gridsize+\gridlinewidth".
By default, the created grids are in black. However, if you give the
-commands\indc{colorgrids}
+commands\indc{colorgrids}\index{color package}
\begin{center}
\begin{tabular}{l}
\verb"\usepackage{color}"\\
@@ -4514,7 +4581,7 @@
or \verb"\pagestyle{foot}" (see section~\ref{sec:pagestyle}), and put
the following into your preamble (i.e., after the
\verb"\documentclass" command and before the \verb"\begin{document}"
- command):
+ command):\index{color package}\indc{gridfromfoot}
\begin{verbatim}
\usepackage{color}
\colorgrids
@@ -4736,14 +4803,13 @@
\subsection{Solution environments}
\label{sec:SolEnv}
\index{solutions|(}
-\index{solution environment|(}
+\index{solution environment@\texttt{solution} environment|(}
\index{answers|(}
-\index{environment!solution|(}
-\index{environment!solutionorbox|(}
-\index{environment!solutionorlines|(}
-\index{environment!solutionordottedlines|(}
-\index{environment!solutionorgrid|(}
-\index{solution environment|(}
+\index{environment!solution@\texttt{solution}|(}
+\index{environment!solutionorbox@\texttt{solutionorbox}|(}
+\index{environment!solutionorlines@\texttt{solutionorlines}|(}
+\index{environment!solutionordottedlines@\texttt{solutionordottedlines}|(}
+\index{environment!solutionorgrid@\texttt{solutionorgrid}|(}
\index{solutionorbox environment|(}
\index{solutionorlines environment|(}
\index{solutionordottedlines environment|(}
@@ -4774,7 +4840,7 @@
The six environments for solutions are divided into two types.
\begin{itemize}
-\item The \texttt{solutionorbox} environment (see
+\item The \texttt{solutionbox} environment (see
section~\ref{sec:solutionbox}) always prints a box, of whatever size
you choose, and if solutions are being printed it prints the
solution inside of the box.
@@ -4796,10 +4862,11 @@
differ only in the type of space they leave when you do include the
optional argument and solutions are not being printed.
-
The differences between these five environments are that if the
- optional argument is used and solutions are not being printed,
- then\index{solution environment!optional argument}
+ optional argument is used and solutions are not being printed, then
+ %
+ \index{solution environment@\texttt{solution} environment!optional argument}
+ %
\begin{itemize}
\item the \verb"solution" enviroment inserts that amount of blank
space, as if you had given a \verb"\vspace*"\indc{vspace*} command
@@ -4831,15 +4898,14 @@
the page, and do not affect any gradetables or pointtables.
-\index{solution environment|)}
\index{solutionorbox environment|)}
\index{solutionorlines environment|)}
\index{solutionordottedlines environment|)}
-\index{environment!solution|)}
-\index{environment!solutionorbox|)}
-\index{environment!solutionorlines|)}
-\index{environment!solutionordottedlines|)}
-\index{environment!solutionorgrid|)}
+\index{environment!solution@\texttt{solution}|)}
+\index{environment!solutionorbox@\texttt{solutionorbox}|)}
+\index{environment!solutionorlines@\texttt{solutionorlines}|)}
+\index{environment!solutionordottedlines@\texttt{solutionordottedlines}|)}
+\index{environment!solutionorgrid@\texttt{solutionorgrid}|)}
%--------------------------------------------------------------------
\subsection{The appearance of the solution}
@@ -4864,7 +4930,10 @@
\item with no framing or shading (see section~\ref{sec:SolPlain}).
\end{itemize}
In all of these cases, solutions can be broken across pages, and the
-part on each page will be boxed or shaded as appropriate.
+part on each page will be boxed or shaded as appropriate. In
+addition, the \verb"\SolutionEmphasis" command can be used to
+highlight the text of the solution (using, e.g., boldface, or italics,
+or color); see section~\ref{sec:SolEmph}.
%--------------------------------------------------------------------
@@ -4874,7 +4943,8 @@
By default, the solution is printed inside of a box (i.e., an
\verb"\fbox"\indc{fbox}), and if the solution is broken across pages,
-then each piece is enclosed in a box. There is also a
+then each piece is enclosed in a box. (The box can be printed in
+color; for that, see section~\ref{sec:colorboxes}.) There is also a
\verb"\shadedsolutions"\indc{shadedsolutions} command to instead have
the solution printed in a \verb"\colorbox"\indc{colorbox} (i.e.,
printed on a shaded background); for this, you must load the
@@ -5040,6 +5110,56 @@
\index{solution!no framing or shading|)}
%--------------------------------------------------------------------
+\subsection{Imported graphics in solutions}
+\label{sec:graphics}
+\index{graphics|(}
+\indc{includegraphics}
+
+Graphics can be included inside solution environments using the
+\verb"\includegraphics" command, as long as you've given the command
+\verb"\usepackage{graphicx}" in the preamble (i.e., after the
+\verb"\documentclass" command and before the \verb"\begin{document}"
+ command).
+
+A problem sometimes arises because many \LaTeX{} manuals say that you
+should put an \verb"\includegraphics" command inside of a
+\texttt{figure} environment, so that it will float to a convenient
+place on a page. The problem with this is that floating environments
+can't appear inside of a solution environment.
+
+There are (at least) two solutions to this problem, depending on
+whether you really want the graphic to float away from the location at
+which you've typed it.
+\begin{itemize}
+\item If you want the graphic to float, put the \texttt{figure}
+ environment \emph{outside} of the solution environment, using
+ \verb"\ifprintanswers" to ensure that it's printed only when
+ solutions are being printed, as in
+\begin{verbatim}
+\ifprintanswers
+ \begin{figure}
+ \includegraphics[width=7cm]{myfigure.pdf}
+ \caption{This is a lovely figure}
+ \label{fig:lovely}
+ \end{figure}
+\fi
+\end{verbatim}
+\item If you \emph{don't} want the graphic to float, then omit the
+ \texttt{figure} environment and just put the \verb"\includegraphics"
+ command wherever you want the graphic to appear. If you want the
+ graphic to have a caption, then put the command
+ \verb"\usepackage{caption}" in your preamble and then use the
+ \verb"\captionof" command, as in
+\begin{verbatim}
+\includegraphics[width=7cm]{myfigure.pdf}
+\captionof{figure}{This is a lovely figure}
+\label{fig:lovely}
+\end{verbatim}
+\end{itemize}
+
+\index{graphics|)}
+
+%--------------------------------------------------------------------
\subsection{Customizing the solution}
\label{sec:SolCust}
\index{customization!solution|(}
@@ -5162,7 +5282,7 @@
\label{sec:SolSpace}
\index{space!for answers|(}
\index{answer space|(}
-\index{solution environment!optional argument|(}
+\index{solution environment@\texttt{solution} environment!optional argument|(}
Each of the \texttt{solution}, \texttt{solutionorbox},
\texttt{solutionorlines}, \texttt{solutionordottedlines}, and
@@ -5170,8 +5290,10 @@
\begin{itemize}
\item In a
%
- \verb"solution"\indtsub{solution}{optional argument}
+ \verb"solution"
%
+ \index{solution environment@\texttt{solution} environment!optional argument}
+ %
environment this is an amount of blank space to be left (just as if
you had used a \verb"\vspace*"\indc{vspace*} command; see
section~\ref{sec:BlankSpace}) when solutions are not being printed,
@@ -5313,13 +5435,16 @@
\emph{Note:} The document class option \texttt{cancelspace} and the
command \verb"\cancelspace" only affect the optional arguments of of
-the five solution environments; they do \emph{not} affect any
-\verb"\vspace" commands that you put into the file.
+the five solution environments \texttt{solution},
+\texttt{solutionorbox}, \texttt{solutionorlines},
+\texttt{solutionordottedlines}, and \texttt{solutionorgrid}; they do
+\emph{not} affect any \verb"\vspace" commands that you put into the
+file.
\indcstop{nocancelspace}
\indcstop{cancelspace}
-\index{solution environment!optional argument|)}
+\index{solution environment@\texttt{solution} environment!optional argument|)}
%--------------------------------------------------------------------
\subsection{The solutionbox environment}
@@ -5348,8 +5473,12 @@
\end{enumerate}
If answers are not being printed then only the box is printed, with
nothing in it. If answers are being printed, then the solution is
-printed inside of the box.
+printed inside of the box. (The box printed by the
+\texttt{solutionbox} environment can be printed in color; for that,
+see section~\ref{sec:colorboxes}.)
+
+
For example, if you type
\begin{verbatim}
\begin{solutionbox}{2in}
@@ -5375,12 +5504,70 @@
If solutions \emph{are} being printed, then the exact same box would
be printed, but it would have the solution printed inside of it.
-
-
\index{answer space|)}
\index{space!for answers|)}
+%--------------------------------------------------------------------
+\subsection{Solution box frames in color}
+\label{sec:colorboxes}
+The frames that are printed by the commands that create solution boxes
+can be printed in color. (By ``frame'' we mean the four lines that
+constitute the box, not any solution that may appear inside that box.)
+This includes
+\begin{itemize}
+\item the box printed by the \texttt{solutionbox}
+ environment\index{customization!\texttt{solutionbox}}
+ (see section~\ref{sec:solutionbox}),
+\item the box printed by the \verb"\makeemptybox"
+ command\index{customization!\texttt{\char`\\makeemptybox}}
+ (see section~\ref{sec:EmptyBox}),
+\item the box printed by the optional argument of the
+ \texttt{solutionorbox}
+ environment\index{customization!\texttt{solutionorbox}} (see
+ section~\ref{sec:SolEnv}), and
+\item the box printed around the solution by
+ the\index{customization!\texttt{solution} environments}
+ \begin{itemize}
+ \item \texttt{solution},
+ \item \texttt{solutionorbox},
+ \item \texttt{solutionorlines},
+ \item \texttt{solutionordottedlines}, and
+ \item \texttt{solutionorgrid}
+ \end{itemize}
+ environments when solutions are being printed and the default
+ solution appearance (\verb"\framedsolutions") is being used (see
+ section~\ref{sec:SolBox}).
+\end{itemize}
+
+If you've given the command
+\begin{center}
+ \verb"\usepackage{color}"\index{color package}
+\end{center}
+in the preamble of your document (i.e., after the
+\verb"\documentclass" command and before the \verb"\begin{document}"
+command), then you can give the command\indc{colorsolutionboxes}
+\begin{center}
+ \verb"\colorsolutionboxes"
+\end{center}
+to have the frame printed in color. The color of the frame will be
+\texttt{SolutionBoxColor}, the default value of which was created by
+the command\indc{definecolor}\indt{SolutionBoxColor}
+\begin{center}
+ \verb"\definecolor{SolutionBoxColor}{gray}{0.8}"
+\end{center}
+You can change the color by giving a new \verb"\definecolor" command,
+but you must do this \emph{after} the \verb"\colorsolutionboxes"
+command.
+
+To cancel color \texttt{solutionbox} frames and return to black, give
+the command\indc{nocolorsolutionboxes}
+\begin{center}
+ \verb"\nocolorsolutionboxes"
+\end{center}
+
+
+
%--------------------------------------------------------------------
\subsection{Changes depending on whether or not solutions are
being printed}
@@ -5473,7 +5660,7 @@
\indcstop{ifprintanswers}
\index{answers|)}
-\index{solution environment|)}
+\index{solution environment@\texttt{solution} environment|)}
\index{solutions|)}
@@ -5721,15 +5908,194 @@
\item create grading ranges (see section~\ref{sec:PartialTable}) and
print several partial grading tables, making each one small enough
to fit on the page, or
-\item use the \verb"\pointsofquestion" command (see
- section~\ref{sec:pointsofq}) or the \verb"\pointsonpage" command
- (see section~\ref{sec:pointsonp}) to create a custom \verb"tabular"
- environment that has more rows (or columns) than the tables produced
- by the \verb"gradingtable" command.
+\item use the \verb"\multirowgradetable" or
+ \verb"\multicolumngradetable" command (see section~\ref{sec:MulRows}
+ and section~\ref{sec:MulCols}) to create a grading table with
+ multiple rows or multiple columns.
\end{itemize}
\index{grading table!by question number or page number|)}
%--------------------------------------------------------------------
+\subsubsection{Grading tables with multiple rows}
+\label{sec:MulRows}
+
+If you want to print a horizontal grading table but the table would be
+too large for the page, you can print a grading table with multiple
+rows by giving the command
+\begin{center}
+ \verb"\multirowgradetable{numrows}[questions or pages]"
+\end{center}
+\indc{multirowgradetable}Note that the first argument
+(\texttt{numrows}) is \emph{required}, and so it is enclosed in
+braces, but the second argument (\texttt{questions} or \texttt{pages})
+is optional, and is enclosed in square brackets, just as in the
+\verb"\gradetable" command (see section~\ref{sec:GradeTables}). For
+example, to print a grading table with 3 rows indexed by questions,
+you would give the command
+\begin{center}
+ \verb"\multirowgradetable{3}[questions]"
+\end{center}
+The command
+\begin{center}
+ \verb"\gradetable[h][questions]"
+\end{center}
+is equivalent to
+\begin{center}
+ \verb"\multirowgradetable{1}[questions]"
+\end{center}
+
+The distance between the rows of a multirow table is
+\verb"\doublerulesep", the default value of which is 2.0pt. You can
+change that using a \verb"\setlength" command, as in
+\begin{center}
+ \verb"\setlength{\doublerulesep}{0.5in}"
+\end{center}
+(see section~\ref{sec:CustTable}).
+
+For example, if an exam has 16 questions, each worth a total of 15
+points, and you type
+\begin{verbatim}
+\begin{center}
+ \setlength{\doublerulesep}{0.25in}
+ \multirowgradetable{2}[questions]
+\end{center}
+\end{verbatim}
+then you'll get
+\begin{center}
+ \setlength{\doublerulesep}{0.25in}
+ \cwidth=2em
+ \renewcommand{\arraystretch}{1.5}
+ \begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+ \hline
+ Question:& 1& 2& 3& 4& 5& 6& 7& 8& 9\\
+ \hline
+ Points:&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15\\
+ \hline
+ Score:&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \\
+ \hline
+ \hline
+ Question:& 10& 11& 12& 13& 14& 15& 16&& Total\\
+ \hline
+ Points:&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15&
+ 15&
+ &
+ 240\\
+ \hline
+ Score:&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \hbox to \cwidth{\hfill}&
+ \\
+ \hline
+ \end{tabular}
+\end{center}
+
+
+%--------------------------------------------------------------------
+\subsubsection{Grading tables with multiple columns}
+\label{sec:MulCols}
+
+If you want to print a vertical grading table but the table would be
+too large for the page, you can print a grading table with multiple
+columns by giving the command
+\begin{center}
+ \verb"\multicolumngradetable{numcols}[questions or pages]"
+\end{center}
+\indc{multicolumngradetable}Note that the first argument
+(\texttt{numcols}) is \emph{required}, and so it is enclosed in
+braces, but the second argument (\texttt{questions} or \texttt{pages})
+is optional, and is enclosed in square brackets, just as in the
+\verb"\gradetable" command (see section~\ref{sec:GradeTables}). For
+example, to print a grading table with 3 columns indexed by questions,
+you would give the command
+\begin{center}
+ \verb"\multicolumngradetable{3}[questions]"
+\end{center}
+The command
+\begin{center}
+ \verb"\gradetable[v][questions]"
+\end{center}
+is equivalent to
+\begin{center}
+ \verb"\multicolumngradetable{1}[questions]"
+\end{center}
+
+The distance between the columns of a multicolumn table is
+\verb"\doublerulesep", the default value of which is 2.0pt. You can
+change that using a \verb"\setlength" command, as in
+\begin{center}
+ \verb"\setlength{\doublerulesep}{0.5in}"
+\end{center}
+(see section~\ref{sec:CustTable}).
+
+For example, if an exam has 10 questions, each worth a total of 15
+points, and you type
+\begin{verbatim}
+\begin{center}
+ \setlength{\doublerulesep}{0.5in}
+ \multicolumngradetable{2}[questions]
+\end{center}
+\end{verbatim}
+then you'll get
+\begin{center}
+ \cwidth=2em
+ \setlength{\doublerulesep}{0.5in}
+ \renewcommand{\arraystretch}{1.5}
+ \begin{tabular}{|c|c|c|c|c|c|c|}
+ \cline{1-3}\cline{5-7}
+ Question& Points& Score&
+ \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}&
+ Question& Points& Score\\
+ \cline{1-3}\cline{5-7}
+ 1& 15& \hbox to \cwidth{\hfill}&&7& 15& \hbox to \cwidth{\hfill}\\
+ \cline{1-3}\cline{5-7}
+ 2& 15& \hbox to \cwidth{\hfill}&&8& 15& \hbox to \cwidth{\hfill}\\
+ \cline{1-3}\cline{5-7}
+ 3& 15& \hbox to \cwidth{\hfill}&&9& 15& \hbox to \cwidth{\hfill}\\
+ \cline{1-3}\cline{5-7}
+ 4& 15& \hbox to \cwidth{\hfill}&&10& 15& \hbox to \cwidth{\hfill}\\
+ \cline{1-3}\cline{5-7}
+ 5& 15& \hbox to \cwidth{\hfill}&& & & \hbox to \cwidth{\hfill}\\
+ \cline{1-3}\cline{5-7}
+ 6& 15& \hbox to \cwidth{\hfill}&&Total:& 150& \hbox to \cwidth{\hfill}\\
+ \cline{1-3}\cline{5-7}
+
+ \cline{1-3}\cline{5-7}
+ \end{tabular}
+\end{center}
+
+
+
+%--------------------------------------------------------------------
\subsection{Point tables indexed by question number or by page
number}
\label{sec:PointTables}
@@ -5893,15 +6259,88 @@
\item create grading ranges (see section~\ref{sec:PartialTable}) and
print several partial point tables, making each one small enough
to fit on the page, or
-\item use the \verb"\pointsofquestion" command (see
- section~\ref{sec:pointsofq}) or the \verb"\pointsonpage" command
- (see section~\ref{sec:pointsonp}) to create a custom \verb"tabular"
- environment that has more rows (or columns) than the tables produced
- by the \verb"pointtable" command.
+\item use the \verb"\multirowpointtable" or
+ \verb"\multicolumnpointtable" command (see
+ section~\ref{sec:PtMulRows} and section~\ref{sec:PtMulCols}) to
+ create a point table with multiple rows or multiple columns.
\end{itemize}
\index{point table!by question number or page number|)}
%--------------------------------------------------------------------
+\subsubsection{Point tables with multiple rows}
+\label{sec:PtMulRows}
+
+If you want to print a horizontal point table but the table would be
+too large for the page, you can print a point table with multiple
+rows by giving the command
+\begin{center}
+ \verb"\multirowpointtable{numrows}[questions or pages]"
+\end{center}
+\indc{multirowpointtable}Note that the first argument
+(\texttt{numrows}) is \emph{required}, and so it is enclosed in
+braces, but the second argument (\texttt{questions} or \texttt{pages})
+is optional, and is enclosed in square brackets, just as in the
+\verb"\pointtable" command (see section~\ref{sec:PointTables}). For
+example, to print a point table with 3 rows indexed by questions, you
+would give the command
+\begin{center}
+ \verb"\multirowpointtable{3}[questions]"
+\end{center}
+The command
+\begin{center}
+ \verb"\pointtable[h][questions]"
+\end{center}
+is equivalent to
+\begin{center}
+ \verb"\multirowpointtable{1}[questions]"
+\end{center}
+
+The distance between the rows of a multirow table is
+\verb"\doublerulesep", the default value of which is 2.0pt. You can
+change that using a \verb"\setlength" command, as in
+\begin{center}
+ \verb"\setlength{\doublerulesep}{0.5in}"
+\end{center}
+(see section~\ref{sec:CustTable}).
+
+%--------------------------------------------------------------------
+\subsubsection{Point tables with multiple columns}
+\label{sec:PtMulCols}
+
+If you want to print a vertical point table but the table would be
+too large for the page, you can print a point table with multiple
+columns by giving the command
+\begin{center}
+ \verb"\multicolumnpointtable{numcols}[questions or pages]"
+\end{center}
+\indc{multicolumnpointtable}Note that the first argument
+(\texttt{numcols}) is \emph{required}, and so it is enclosed in
+braces, but the second argument (\texttt{questions} or \texttt{pages})
+is optional, and is enclosed in square brackets, just as in the
+\verb"\pointtable" command (see section~\ref{sec:PointTables}). For
+example, to print a point table with 3 columns indexed by questions,
+you would give the command
+\begin{center}
+ \verb"\multicolumnpointtable{3}[questions]"
+\end{center}
+The command
+\begin{center}
+ \verb"\pointtable[v][questions]"
+\end{center}
+is equivalent to
+\begin{center}
+ \verb"\multicolumnpointtable{1}[questions]"
+\end{center}
+
+The distance between the columns of a multicolumn table is
+\verb"\doublerulesep", the default value of which is 2.0pt. You can
+change that using a \verb"\setlength" command, as in
+\begin{center}
+ \verb"\setlength{\doublerulesep}{0.5in}"
+\end{center}
+(see section~\ref{sec:CustTable}).
+
+%--------------------------------------------------------------------
\subsection{Table entries as clickable links}
\label{sec:Clickable}
\index{grading table!clickable links}
@@ -5932,7 +6371,8 @@
will be clickable links that take you to the corresponding question.
%--------------------------------------------------------------------
-\subsection{Grading ranges, partial grading tables, and partial point tables}
+\subsection{Grading ranges, partial grading tables, and partial point
+ tables}
\label{sec:PartialTable}
\index{grading range|(}
\indcstart{begingradingrange}
@@ -6006,7 +6446,92 @@
\indcstop{begingradingrange}
\index{grading range|)}
+
%--------------------------------------------------------------------
+\subsubsection{Partial grading tables and partial point tables with
+ multiple rows}
+\label{sec:PartMulRows}
+
+If you want to print a horizontal partial grading table or partial
+point table but the table would be too large for the page, you can
+print a partial grading table or partial point table with multiple
+rows by giving the one of the commands
+\begin{center}
+ \verb"\multirowpartialgradetable{numrows}{rangename}[questions or pages]"
+ \verb"\multirowpartialpointtable{numrows}{rangename}[questions or pages]"
+\end{center}
+\indc{multirowpartialgradetable}\indc{multirowpartialpointtable}Note
+that the first two arguments (\texttt{numrows} and \texttt{rangename})
+are \emph{required}, and so they are enclosed in braces, but the third
+argument (\texttt{questions} or \texttt{pages}) is optional, and is
+enclosed in square brackets, just as in the \verb"\partialgradetable"
+and \verb"\partialpointtable" commands (see
+section~\ref{sec:PartialTable}). For example, to print a partial
+grading table with 3 rows covering the range \texttt{myrange} indexed
+by questions, you would give the command
+\begin{center}
+ \verb"\multirowpartialgradetable{3}{myrange}[questions]"
+\end{center}
+The command
+\begin{center}
+ \verb"\partialgradetable{myrange}[h][questions]"
+\end{center}
+is equivalent to
+\begin{center}
+ \verb"\multirowpartialgradetable{1}{myrange}[questions]"
+\end{center}
+
+The distance between the rows of a multirow table is
+\verb"\doublerulesep", the default value of which is 2.0pt. You can
+change that using a \verb"\setlength" command, as in
+\begin{center}
+ \verb"\setlength{\doublerulesep}{0.5in}"
+\end{center}
+(see section~\ref{sec:CustTable}).
+
+%--------------------------------------------------------------------
+\subsubsection{Partial grading tables and partial point tables with
+ multiple columns}
+\label{sec:PartMulCols}
+
+If you want to print a vertical partial grading table or partial point
+table but the table would be too large for the page, you can print a
+partial grading table or partial point table with multiple columns by
+giving one of the commands
+\begin{center}
+\verb"\multicolumnpartialgradetable{numcols}{rangename}[questions or pages]"\\
+\verb"\multicolumnpartialpointtable{numcols}{rangename}[questions or pages]"
+\end{center}
+\indc{multicolumnpartialgradetable}\indc{multicolumnpartialpointtable}Note
+that the first two arguments (\texttt{numcols} and
+\texttt{rangename}) are \emph{required}, and so they are enclosed in
+braces, but the third argument (\texttt{questions} or \texttt{pages})
+is optional, and is enclosed in square brackets, just as in the
+\verb"\partialgradetable" and \verb"\partialpointtable" commands (see
+section~\ref{sec:PartialTable}). For example, to print a partial
+grading table with 3 columns covering the range \texttt{myrange}
+indexed by questions, you would give the command
+\begin{center}
+ \verb"\multicolumnpartialgradetable{3}{myrange}[questions]"
+\end{center}
+The command
+\begin{center}
+ \verb"\partialgradetable{myrange}[v][questions]"
+\end{center}
+is equivalent to
+\begin{center}
+ \verb"\multicolumnpartialgradetable{1}{myrange}[questions]"
+\end{center}
+
+The distance between the columns of a multicolumn table is
+\verb"\doublerulesep", the default value of which is 2.0pt. You can
+change that using a \verb"\setlength" command, as in
+\begin{center}
+ \verb"\setlength{\doublerulesep}{0.5in}"
+\end{center}
+(see section~\ref{sec:CustTable}).
+
+%--------------------------------------------------------------------
\subsection{\texttt{\bs pointsofquestion}}
\label{sec:pointsofq}
@@ -6114,29 +6639,59 @@
points. (There are also commands that create tables listing both
non-bonus and bonus points; see section~\ref{sec:CombinedTables}.)
These commands, and the non-bonus commands to which they correspond,
-are as follows:\indc{bonusgradetable}\indc{bonuspointtable}%
-\indc{bonuspointsinrange}\indc{partialbonusgradetable}%
-\indc{partialbonuspointtable}\indc{bonuspointsofquestion}%
-\indc{bonuspointsonpage}
+are as follows:
\begin{center}
\begin{tabular}{l@{\qquad\qquad}l}
Bonus points& Non-bonus points\\[\bigskipamount]
\verb"\bonusgradetable"& \verb"\gradetable"\\
- \verb"\bonuspointtable"& \verb"\pointtable"\\[\medskipamount]
- \verb"\bonuspointsinrange"& \verb"\pointsinrange"\\
+ \verb"\multirowbonusgradetable"& \verb"\multirowgradetable"\\
+ \verb"\multicolumnbonusgradetable"& \verb"\multicolumngradetable"\\
+ \verb"\bonuspointtable"& \verb"\pointtable"\\
+ \verb"\multirowbonuspointtable"& \verb"\multirowpointtable"\\
+ \verb"\multicolumnbonuspointtable"&
+ \verb"\multicolumnpointtable"\\[\medskipamount]
\verb"\partialbonusgradetable"& \verb"\partialgradetable"\\
+ \verb"\multirowpartialbonusgradetable"&
+ \verb"\multirowpartialgradetable"\\
+ \verb"\multicolumnpartialbonusgradetable"&
+ \verb"\multicolumnpartialgradetable"\\
\verb"\partialbonuspointtable"&
- \verb"\partialpointtable"\\[\medskipamount]
+ \verb"\partialpointtable"\\
+ \verb"\multirowpartialbonuspointtable"&
+ \verb"\multirowpartialpointtable"\\
+ \verb"\multicolumnpartialbonuspointtable"&
+ \verb"\multicolumnpartialpointtable"\\[\medskipamount]
+ \verb"\bonuspointsinrange"& \verb"\pointsinrange"\\
\verb"\bonuspointsofquestion"& \verb"\pointsofquestion"\\
\verb"\bonuspointsonpage"& \verb"\pointsonpage"
\end{tabular}
\end{center}
+\indc{bonusgradetable}\indc{bonuspointtable}%
+\indc{bonuspointsinrange}\indc{partialbonusgradetable}%
+\indc{partialbonuspointtable}\indc{bonuspointsofquestion}%
+\indc{bonuspointsonpage}%
+\indc{multirowbonusgradetable}%
+\indc{multicolumnbonusgradetable}%
+\indc{multirowbonuspointtable}%
+\indc{multicolumnbonuspointtable}%
+\indc{multirowpartialbonusgradetable}%
+\indc{multicolumnpartialbonusgradetable}%
+\indc{multirowpartialbonuspointtable}%
+\indc{multicolumnpartialbonuspointtable}%
All of the the commands in the first column count bonus points and
ignore non-bonus points, while all of the commands in the second
-column count non-bonus points and ignore bonus points. The
-\verb"\partialbonusgradetable" and \verb"\partialbonuspointtable"
-commands use the same
-\verb"\begingradingrange"\indc{begingradingrange} and
+column count non-bonus points and ignore bonus points. The commands
+\begin{center}
+ \begin{tabular}{l}
+ \verb"\partialbonusgradetable",\\
+ \verb"\multirowpartialbonusgradetable",\\
+ \verb"\multicolumnpartialbonusgradetable",\\
+ \verb"\partialbonuspointtable",\\
+ \verb"\multirowpartialbonuspointtable", and\\
+ \verb"\multicolumnpartialbonuspointtable"
+ \end{tabular}
+\end{center}
+use the same \verb"\begingradingrange"\indc{begingradingrange} and
\verb"\endgradingrange"\indc{endgradingrange} commands that are used
by the corresponding non-bonus versions (see
section~\ref{sec:PartialTable}). Just as is described in
@@ -6214,14 +6769,15 @@
There are commands for producing \emph{combined} grading and point
tables, both partial and full, that tabulate both regular points and
-bonus points (see section~\ref{sec:Bonus}). These commands, and the
+bonus points (see section~\ref{sec:Bonus}). The single-row and
+single-column versions of these commands, and the
non-bonus and bonus commands to which they correspond, are
\indc{combinedgradetable}\indc{combinedpointtable}%
\indc{partialcombinedgradetable}\indc{partialcombinedpointtable}%
\begin{center}
\begin{tabular}{l@{\enskip}l@{\enskip}l}
- Non-Bonus points only& Bonus points only&
- Combined\\[\medskipamount]
+ Non-Bonus points only& \multicolumn{1}{c}{Bonus points only}&
+ \multicolumn{1}{c}{Combined}\\[\medskipamount]
\verb"\gradetable"& \verb"\bonusgradetable"&
\verb"\combinedgradetable"\\
\verb"\pointtable"& \verb"\bonuspointtable"&
@@ -6242,6 +6798,37 @@
first being either \verb"[v]" or \verb"[h]" and the second being
either \verb"[questions]" or \verb"[pages]").
+The multirow and multicolumn versions of combined grading tables and
+combined point tables are produced by the commands
+\indc{multirowcombinedgradetable}%
+\indc{multirowcombinedpointtable}%
+\indc{multirowpartialcombinedgradetable}%
+\indc{multirowpartialcombinedpointtable}%
+\indc{multicolumncombinedgradetable}%
+\indc{multicolumncombinedpointtable}%
+\indc{multicolumnpartialcombinedgradetable}%
+\indc{multicolumnpartialcombinedpointtable}%
+\begin{verbatim}
+\multirowcombinedgradetable{numrows}[questions or pages]
+\multirowcombinedpointtable{numrows}[questions or pages]
+\multirowpartialcombinedgradetable{numrows}{rangename}[questions or pages]
+\multirowpartialcombinedpointtable{numrows}{rangename}[questions or pages]
+\multicolumncombinedgradetable{numcols}[questions or pages]
+\multicolumncombinedpointtable{numcols}[questions or pages]
+\multicolumnpartialcombinedgradetable{numcols}{rangename}[questions or pages]
+\multicolumnpartialcombinedpointtable{numcols}{rangename}[questions or pages]
+\end{verbatim}
+The distance between the rows of a multirow table and between the
+columns of a multicolumn table is \verb"\doublerulesep", the default
+value of which is 2.0pt. You can change that using a
+\verb"\setlength" command, as in
+\begin{center}
+ \verb"\setlength{\doublerulesep}{0.5in}"
+\end{center}
+(see section~\ref{sec:CustTable}).
+
+
+
Just as is described in section~\ref{sec:Clickable} for their regular
points and section~\ref{sec:BonusTables} for bonus points, if you put
the
@@ -6412,7 +6999,7 @@
\index{grade table!customization|(}
\index{point table!customization|(}
-There are three ways in which you can customize the appearance of
+There are four ways in which you can customize the appearance of
grading tables and point tables:
\begin{itemize}
\item You can change the words (and the fonts) that appear in the
@@ -6421,20 +7008,30 @@
you will write the scores.
\item You can change the value of
\verb"\baselinestretch"\indc{baselinestretch} used for the table.
+\item You can change the distance between the rows in a multirow table
+ and the distance between the columns in a multicolumn table.
\end{itemize}
For all grading and point tables:\indc{gradetablestretch}\indc{cellwidth}
+\indc{doublerulesep}%
\begin{center}
- \begin{tabular}{l@{\qquad}l}
+ \begin{tabular}{l@{\qquad}p{3in}}
\verb"\cellwidth{length}"& sets the minimum width of the blank cells to
- \verb"length"\\
+ \verb"length"\\[\medskipamount]
\verb"\gradetablestretch{number}"& uses \verb"number" as the
- \verb"\baselinestretch"
+ \verb"\baselinestretch"\\[\medskipamount]
+ \verb"\setlength{\doublerulesep}{length}"& sets the distance
+ between the columns of a multicolumn table and the distance
+ between the rows of a multirow table to \verb"length".
\end{tabular}
\end{center}
-For vertical non-bonus tables (i.e., tables created by
-\verb"\gradetable[v]", \verb"\pointtable[v]",
-\verb"\partialgradetable{rangename}[v]", or
-\verb"\partialpointtable{rangename}[v]"):%
+For vertical non-bonus tables:
+% (i.e., tables created by
+% \verb"\gradetable[v]", \verb"\multicolumngradetable",
+% \verb"\pointtable[v]", \verb"\multicolumnpointtable",
+% \verb"\partialgradetable{rangename}[v]",
+% \verb"\multicolumnpartialgradetable",
+% \verb"\partialpointtable{rangename}[v]", or
+% \verb"\multicolumnpartialpointtable"):%
\indc{vqword}\indc{vpgword}\indc{vpword}\indc{vsword}\indc{vtword}
\begin{center}
\begin{tabular}{l@{\qquad}l}
@@ -6446,10 +7043,11 @@
\verb"\vtword{text}"& substitutes \verb"text" for ``Total:''
\end{tabular}
\end{center}
-For horizontal non-bonus tables (i.e., tables created by
-\verb"\gradetable[h]", \verb"\pointtable[h]",
-\verb"\partialgradetable{rangename}[h]", or
-\verb"\partialpointtable{rangename}[h]"):%
+For horizontal non-bonus tables:
+% (i.e., tables created by
+% \verb"\gradetable[h]", \verb"\pointtable[h]",
+% \verb"\partialgradetable{rangename}[h]", or
+% \verb"\partialpointtable{rangename}[h]"):%
\indc{hqword}\indc{hpgword}\indc{hpword}\indc{hsword}\indc{htword}
\begin{center}
\begin{tabular}{l@{\qquad}l}
@@ -6461,11 +7059,13 @@
\verb"\htword{text}"& substitutes \verb"text" for ``Total''
\end{tabular}
\end{center}
-For vertical bonus tables (i.e., tables created by
-\verb"\bonusgradetable[v]", \verb"\bonuspointtable[v]",
-\verb"\partialbonusgradetable{rangename}[v]", or
-\verb"\partialbonuspointtable{rangename}[v]"):\indc{bvqword}%
-\indc{bvpgword}\indc{bvpword}\indc{bvsword}\indc{bvtword}
+For vertical bonus tables:
+% (i.e., tables created by
+% \verb"\bonusgradetable[v]", \verb"\bonuspointtable[v]",
+% \verb"\partialbonusgradetable{rangename}[v]", or
+% \verb"\partialbonuspointtable{rangename}[v]"):
+\indc{bvqword}\indc{bvpgword}\indc{bvpword}\indc{bvsword}%
+\indc{bvtword}
\begin{center}
\begin{tabular}{l@{\qquad}l}
Command& \multicolumn{1}{c}{Effect}\\[\medskipamount]
@@ -6476,11 +7076,13 @@
\verb"\bvtword{text}"& substitutes \verb"text" for ``Total:''
\end{tabular}
\end{center}
-For horizontal bonus tables (i.e., tables created by
-\verb"\bonusgradetable[h]", \\
-\verb"\bonuspointtable[h]",
-\verb"\partialbonusgradetable{rangename}[h]", or\\
-\verb"\partialbonuspointtable{rangename}[h]"):\indc{bhqword}%
+For horizontal bonus tables:
+% (i.e., tables created by
+% \verb"\bonusgradetable[h]", \\
+% \verb"\bonuspointtable[h]",
+% \verb"\partialbonusgradetable{rangename}[h]", or\\
+% \verb"\partialbonuspointtable{rangename}[h]"):
+\indc{bhqword}%
\indc{bhpgword}\indc{bhpword}\indc{bhsword}\indc{bhtword}
\begin{center}
\begin{tabular}{l@{\qquad}l}
@@ -6492,11 +7094,13 @@
\verb"\bhtword{text}"& substitutes \verb"text" for ``Total''
\end{tabular}
\end{center}
-For vertical combined tables (i.e., tables created by
-\verb"\combinedgradetable[v]",\\
-\verb"\combinedpointtable[v]",
-\verb"\partialcombinedgradetable{rangename}[v]", or\\
-\verb"\partialcombinedpointtable{rangename}[v]"):\indc{cvqword}%
+For vertical combined tables:
+% (i.e., tables created by
+% \verb"\combinedgradetable[v]",\\
+% \verb"\combinedpointtable[v]",
+% \verb"\partialcombinedgradetable{rangename}[v]", or\\
+% \verb"\partialcombinedpointtable{rangename}[v]"):
+\indc{cvqword}%
\indc{cvpgword}\indc{cvpword}\indc{cvbpword}\indc{cvsword}%
\indc{cvtword}
\begin{center}
@@ -6510,11 +7114,13 @@
\verb"\cvtword{text}"& substitutes \verb"text" for ``Total:''
\end{tabular}
\end{center}
-For horizontal combined tables (i.e., tables created by
-\verb"\combinedgradetable[h]", \\
-\verb"\combinedpointtable[h]",
-\verb"\partialcombinedgradetable{rangename}[h]", or\\
-\verb"\partialcombinedpointtable{rangename}[h]"):\indc{chqword}%
+For horizontal combined tables:
+% (i.e., tables created by
+% \verb"\combinedgradetable[h]", \\
+% \verb"\combinedpointtable[h]",
+% \verb"\partialcombinedgradetable{rangename}[h]", or\\
+% \verb"\partialcombinedpointtable{rangename}[h]"):
+\indc{chqword}%
\indc{chpgword}\indc{chpword}\indc{chbpword}\indc{chsword}%
\indc{chtword}
\begin{center}
@@ -6529,16 +7135,15 @@
\end{tabular}
\end{center}
If you don't use any of these commands then you get the default
-values, which are defined by the commands in the following table:
+values, which are defined by the commands in the following
+table:\indc{doublerulesep}\indc{gradetablestretch}\indc{cellwidth}
\begin{center}
- \begin{tabular}{l@{\quad}l@{\quad}l}
- \multicolumn{3}{c}{\bfseries Defaults for grading and point
+ \begin{tabular}{l@{\quad}l}
+ \multicolumn{2}{c}{\bfseries Defaults for grading and point
tables}\\*[\bigskipamount]
- \verb"\hqword{Question:}"& \verb"\vqword{Question}"&
- \verb"\cellwidth{2em}"\\
- \verb"\hpgword{Page:}"& \verb"\vpgword{Page}"&
- \verb"\gradetablestretch{1.5}"\\
- \verb"\hpword{Points:}"& \verb"\vpword{Points}"\\
+ \verb"\hqword{Question:}"& \verb"\vqword{Question}"\\
+ \verb"\hpgword{Page:}"& \verb"\vpgword{Page}"\\
+ \verb"\hpword{Points:}"& \verb"\vpword{Points}"\\
\verb"\hsword{Score:}"& \verb"\vsword{Score}"\\
\verb"\htword{Total}"& \verb"\vtword{Total:}"\\[\medskipamount]
%
@@ -6553,7 +7158,10 @@
\verb"\chpword{Points:}"& \verb"\cvpword{Points}"\\
\verb"\chbpword{Bonus Points:}"& \verb"\cvbpword{Bonus Points}"\\
\verb"\chsword{Score:}"& \verb"\cvsword{Score}"\\
- \verb"\chtword{Total}"& \verb"\cvtword{Total:}"
+ \verb"\chtword{Total}"& \verb"\cvtword{Total:}"\\[\medskipamount]
+ \verb"\cellwidth{2em}"\\
+ \verb"\gradetablestretch{1.5}"\\
+ \verb"\setlength{\doublerulesep}{2.0pt}"
\end{tabular}
\end{center}
@@ -6888,7 +7496,8 @@
\indcstop{runningheader}
%--------------------------------------------------------------------
-\subsubsection{Using \texttt{\bs lhead}, \texttt{\bs chead} and \texttt{\bs rhead}}
+\subsubsection{Using \texttt{\bs lhead}, \texttt{\bs chead} and
+ \texttt{\bs rhead}}
\label{sec:lhead}
\indcstart{lhead}
\indcstart{chead}
@@ -7022,7 +7631,8 @@
\indcstop{runningfooter}
%--------------------------------------------------------------------
-\subsubsection{Using \texttt{\bs lfoot}, \texttt{\bs cfoot}, and \texttt{\bs rfoot}}
+\subsubsection{Using \texttt{\bs lfoot}, \texttt{\bs cfoot}, and
+ \texttt{\bs rfoot}}
\label{sec:lfoot}
\indcstart{lfoot}
\indcstart{cfoot}
@@ -7102,15 +7712,6 @@
\end{center}
gives a half inch of extra head height on the first page and a
quarter inch of extra head height on all pages after the first.
-If you say
-\begin{center}
- \verb"\extraheadheight[.5in]{}"
-\end{center}
-then this will be interpreted as if it was
-\begin{center}
- \verb"\extraheadheight[.5in]{0in}"
-\end{center}
-Note that the braces \emph{must} appear.
If you give an \verb"\extraheadheight"\indc{extraheadheight} command,
it should be in the preamble, i.e., after the \verb"\documentclass"
@@ -7151,15 +7752,6 @@
\end{center}
gives a half inch of extra foot height on the first page and a
quarter inch of extra foot height on all pages after the first.
-If you say
-\begin{center}
- \verb"\extrafootheight[.5in]{}"
-\end{center}
-then this will be interpreted as if it was
-\begin{center}
- \verb"\extrafootheight[.5in]{0in}"
-\end{center}
-Note that the braces \emph{must} appear.
If you give an \verb"\extrafootheight"\indc{extrafootheight} command,
it should be in the preamble, i.e., after the \verb"\documentclass"
Modified: trunk/Master/texmf-dist/tex/latex/exam/exam.cls
===================================================================
--- trunk/Master/texmf-dist/tex/latex/exam/exam.cls 2017-11-16 22:14:19 UTC (rev 45831)
+++ trunk/Master/texmf-dist/tex/latex/exam/exam.cls 2017-11-16 22:14:35 UTC (rev 45832)
@@ -3,7 +3,8 @@
% A LaTeX2e document class for preparing exams.
%% exam.cls
-%% Copyright (c) 1994, 1997, 2000, 2004, 2008, 2011, 2015 Philip S. Hirschhorn
+%% Copyright (c) 1994, 1997, 2000, 2004, 2008, 2011,
+%% 2015, 2017 Philip S. Hirschhorn
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
@@ -31,8 +32,8 @@
% from my web page: http://www-math.mit.edu/~psh/
-\def\fileversion{2.5}
-\def\filedate{2015/05/07}
+\def\fileversion{2.6}
+\def\filedate{2017/10/26}
%---------------------------------------------------------------------
%---------------------------------------------------------------------
%
@@ -85,6 +86,263 @@
% Changelog since version 2.4:
%--------------------------------------------------------------------
+% Version 2.6, 2017/09/19
+
+% No longer betatest.
+
+%--------------------------------------------------------------------
+% Version 2.510$\beta$, 2016/10/11
+
+% Bugfix: We changed \@setheadheight and \@setfootheight to fix a bug
+% that was introduced by the bugfix in version 2.306beta, 2009/03/28:
+% If the second page has a different \textheight (because of a change
+% in either headheight or footheight between pages 1 and 2), then page
+% 2 would use the \textheight of page 1. Pages 3 and beyond would get
+% the correct \textheight. The original version of this set \@colroom
+% and \vsize to the new \textheight, but that had a bug in that if a
+% float appeared at the top of a page, there would be no notice taken
+% of the space lost to the float, and so the text would overrun the
+% bottom of the page. The bugfix in version 2.306beta eliminated the
+% changes to \@colht and \vsize. In this bugfix, we adjust \@colroom,
+% \@colht, and \vsize in the same way that we adjust \textheight.
+
+%--------------------------------------------------------------------
+% Version 2.509$\beta$, 2016/09/12
+
+% Multicolumn grade and point tables, and a new syntax for multirow
+% grade and point tables (which were introduced in version
+% 2.508beta).
+
+% Multicolumn tables are vertically oriented, while multirow tables
+% are horizontally oriented, and so they do not take the optional
+% argument choosing between horizontal and vertical. They all take
+% one required argument specifying the number of columns (for
+% multicolumn) or the number of rows (for multirow).
+
+% The tables can be:
+
+% grade tables or point tables,
+
+% plain, bonus, or combined,
+
+% indexed by questions or by pages,
+
+% complete or partial.
+
+% As usual, if you omit the optional argument that chooses between
+% questions and pages, you get questions.
+
+% The new commands are:
+
+% \def\multirowgradetable{numrows}[questions or pages]
+% \def\multirowpointtable{numrows}[questions or pages]
+% \def\multirowbonusgradetable{numrows}[questions or pages]
+% \def\multirowbonuspointtable{numrows}[questions or pages]
+% \def\multirowcombinedgradetable{numrows}[questions or pages]
+% \def\multirowcombinedpointtable{numrows}[questions or pages]
+
+% \def\multirowpartialgradetable{numrows}{rangename}[questions or pages]
+% \def\multirowpartialpointtable{numrows}{rangename}[questions or pages]
+% \def\multirowpartialbonusgradetable{numrows}{rangename}[questions or pages]
+% \def\multirowpartialbonuspointtable{numrows}{rangename}[questions or pages]
+% \def\multirowpartialcombinedgradetable{numrows}{rangename}[questions or pages]
+% \def\multirowpartialcombinedpointtable{numrows}{rangename}[questions or pages]
+
+% \def\multicolumngradetable{numcols}[questions or pages]
+% \def\multicolumnpointtable{numcols}[questions or pages]
+% \def\multicolumnbonusgradetable{numcols}[questions or pages]
+% \def\multicolumnbonuspointtable{numcols}[questions or pages]
+% \def\multicolumncombinedgradetable{numcols}[questions or pages]
+% \def\multicolumncombinedpointtable{numcols}[questions or pages]
+
+% \def\multicolumnpartialgradetable{numcols}{rangename}[questions or pages]
+% \def\multicolumnpartialpointtable{numcols}{rangename}[questions or pages]
+% \def\multicolumnpartialbonusgradetable{numcols}{rangename}[questions or pages]
+% \def\multicolumnpartialbonuspointtable{numcols}{rangename}[questions or pages]
+% \def\multicolumnpartialcombinedgradetable{numcols}{rangename}[questions or pages]
+% \def\multicolumnpartialcombinedpointtable{numcols}{rangename}[questions or pages]
+
+% The older grade and point table commands can still be used. For
+% example, the commands
+
+% \gradetable[h][questions]
+% \multirowgradetable{1}[questions]
+
+% are equivalent.
+
+% The distance between the rows of a multirow table and between the
+% columns of a multicolumn table is \doublerulesep, the default value
+% of which is 2.0pt. You can change that using a \setlength command,
+% as in
+
+% \setlength{\doublerulesep}{0.5in}
+
+%--------------------------------------------------------------------
+% Version 2.508$\beta$, 2016/08/06
+
+% New commands: Multirow grade and point tables.
+
+% These are all horizontally oriented tables, and so do not take the
+% optional argument choosing between horizontal and vertical. They all
+% take one required argument specifying the number of columns, which is
+% the number of columns used for the point values (including the total),
+% but not counting the column of row headings.
+
+% Note: The syntax was changed in version 2.509beta, so that you now
+% specify the number of *rows* rather than the number of *columns*! For
+% example, the first command below should now be
+
+% \multirowgradetable{numrows}[questions or pages]
+
+% The tables can be:
+
+% grade tables or point tables,
+
+% plain, bonus, or combined,
+
+% indexed by questions or by pages,
+
+% complete or partial.
+
+% The new commands are:
+
+
+% \multirowgradetable{numcols}[questions or pages]
+% \multirowpointtable{numcols}[questions or pages]
+% \multirowbonusgradetable{numcols}[questions or pages]
+% \multirowbonuspointtable{numcols}[questions or pages]
+% \multirowcombinedgradetable{numcols}[questions or pages]
+% \multirowcombinedpointtable{numcols}[questions or pages]
+
+% \multirowpartialgradetable{numcols}{rangename}[questions or pages]
+% \multirowpartialpointtable{numcols}{rangename}[questions or pages]
+% \multirowpartialbonusgradetable{numcols}{rangename}[questions or pages]
+% \multirowpartialbonuspointtable{numcols}{rangename}[questions or pages]
+% \multirowpartialcombinedgradetable{numcols}{rangename}[questions or pages]
+% \multirowpartialcombinedpointtable{numcols}{rangename}[questions or pages]
+
+%--------------------------------------------------------------------
+% Version 2.507$\beta$, 2016/07/14
+
+% New commands:
+
+% \pointstwosided
+% \pointstwosidedreversed
+
+% The first causes points to be in the right margin on odd numbered
+% pages and in the left margin on even numbered pages.
+
+% The second causes points to be in the left margin on odd numbered
+% pages and in the right margin on even numbered pages.
+
+% Also: Some minor edits (e.g., deleting the unused \thebonuspoints).
+
+%--------------------------------------------------------------------
+% Version 2.506$\beta$, 2016/05/12
+
+% Fixed an obscure bug that arose only when \CorrectChoiceEmphasis
+% used color and a \CorrectChoice (in a choices or checkboxes
+% environment) followed a \choice whose text completely filled its
+% last line, and which was not separated from the \CorrectChoice by a
+% blank line, in which case an extra (blank) line was inserted by that
+% \choice. We fixed this by adding an improvised "\leavehmode"
+% (styled after \leavevmode) to the \CorrectChoice command in both the
+% choices and checkboxes environments, which caused the text of the
+% previous \choice to be broken into lines *before* the \special
+% inserted by the \color command was added.
+
+%--------------------------------------------------------------------
+% Version 2.505$\beta$, 2016/05/10
+
+% We fixed a bug in the choices and checkboxes environments that arose
+% only when \CorrectChoiceEmphasis used color. If it did, and if the
+% text of a correct choice exactly filled a line, and if there was no
+% blank line in the latex file separating this correct choice from the
+% following choice, there would be an extra blank line inserted after
+% the correct choice. We did this by inserting \color at begingroup and
+% \color at endgroup as needed. (We're pretty sure the actual fix was
+% the \endgraf in the expansion of \color at endgroup.)
+
+%--------------------------------------------------------------------
+% Version 2.504$\beta$, 2016/05/09
+
+% We fixed a bug in the solutionbox environment that caused enumerate,
+% itemize, or description environments to have their text stick into
+% the right margin. We did this by resetting \@totalleftmargin and
+% \linewidth in the box containing the solution.
+
+%--------------------------------------------------------------------
+% Version 2.503$\beta$, 2016/03/25
+
+% New commands:
+
+% \colorfillwithlines
+% \colorfillwithdottedlines
+
+% The first causes the lines drawn by the \fillwithlines command to be
+% drawn in color. The default color is set by the command
+
+% \definecolor{FillWithLinesColor}{gray}{0.8}
+
+% and the color can be changed by giving a new \definecolor command.
+% You can return to black lines by giving the command
+
+% \nocolorfillwithlines
+
+% \colorfillwithdottedlines causes the lines drawn by the
+% \fillwithdottedlines command to be drawn in color. The default
+% color is set by the command
+
+% \definecolor{FillWithDottedLinesColor}{gray}{0.8}
+
+% and the color can be changed by giving a new \definecolor command.
+% You can return to black dotted lines by giving the command
+
+% \nocolorfillwithdottedlines
+
+%--------------------------------------------------------------------
+% Version 2.502$\beta$, 2016/03/23
+
+% The command
+
+% \colorsolutionboxes
+
+% that was created in version 2.501beta now affects not only the boxes
+% created by \solutionbox, but also by \makeemptybox, \solutionorbox,
+% and all of the boxes printed by all of the various solution
+% environments when solutions are being printed surrounded by a box.
+
+%--------------------------------------------------------------------
+% Version 2.501$\beta$, 2016/02/08
+
+% Changed the \solutionbox environment so that it works correctly
+% inside a tabular.
+
+% Also: The \solutionbox frame can now be printed in color, as long as
+% you load color.sty in the preamble.
+%
+% Usage: Say
+%
+% \usepackage{color}
+%
+% in the preamble, and then give the command
+%
+% \colorsolutionboxes
+%
+% to have the frame around a solutionbox in color. The default color
+% was created by the command
+%
+% \definecolor{SolutionBoxColor}{gray}{0.8}
+%
+% and you can change the color by giving a new \definecolor command
+% (which must be done *after* the \colorsolutionboxes command).
+%
+% To cancel color solutionbox frames and return to black, give the
+% command
+%
+% \nocolorsolutionboxes
+
+%--------------------------------------------------------------------
% Version 2.5 2015/05/07
% No longer betatest.
@@ -552,6 +810,11 @@
% Reset the effect of the most recent change:
\global\advance\topmargin by -\@extrahead
\global\advance\textheight by \@extrahead
+ % Bugfix, Version 2.510beta, 2016/10/11:
+ \global\advance\@colroom by \@extrahead
+ \global\advance\@colht by \@extrahead
+ \global\advance\vsize by \@extrahead
+ %
% Save the newly set value:
\def\@temp{#1}
\def\@spaces{ }
@@ -567,6 +830,26 @@
% Set the new values:
\global\advance\topmargin by \@extrahead
\global\advance\textheight by -\@extrahead
+ % Bugfix, Version 2.510beta, 2016/10/11:
+ \global\advance\@colroom by -\@extrahead
+ \global\advance\@colht by -\@extrahead
+ \global\advance\vsize by -\@extrahead
+ %
+ % Bugfix, Version 2.510beta, 2016/10/11:
+ % We're fixing a bug that was introduced by the bugfix in version
+ % 2.306beta, 2009/03/28: If the second page has a different
+ % \textheight (because of a change in either headheight or
+ % footheight between pages 1 and 2), then page 2 would use the
+ % \textheight of page 1. Pages 3 and beyond would get the correct
+ % \textheight.
+ % The original version of this set \@colroom and \vsize to the new
+ % \textheight, but that had a bug in that if a float appeared at
+ % the top of a page, there would be no notice taken of the space
+ % lost to the float, and so the text would overrun the bottom of
+ % the page.
+ % In this bugfix, we adjust \@colroom, \@colht, and \vsize in the
+ % same way that we adjust \textheight.
+ %
% 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
@@ -584,17 +867,23 @@
% We *do* need to put \@colht at the correct new value, though,
% apparently because \@colht is set near the end of the
% output routine.
- \global\@colht=\textheight
+% \global\@colht=\textheight
+%
% \global\@colroom=\textheight
% \global\vsize=\textheight
% \global\pagegoal=\textheight
\endgroup
-}
+}% @setheadheight
\def\@setfootheight#1{%
\begingroup % Avoid trouble from using \@temp and \@spaces
% Reset the effect of the most recent change:
\global\advance\textheight by \@extrafoot
+ % Bugfix, Version 2.510beta, 2016/10/11:
+ \global\advance\@colroom by \@extrafoot
+ \global\advance\@colht by \@extrafoot
+ \global\advance\vsize by \@extrafoot
+ %
% Save the newly set value:
\def\@temp{#1}
\def\@spaces{ }
@@ -609,6 +898,26 @@
\fi
% Set the new values:
\global\advance\textheight by -\@extrafoot
+ % Bugfix, Version 2.510beta, 2016/10/11:
+ \global\advance\@colroom by -\@extrafoot
+ \global\advance\@colht by -\@extrafoot
+ \global\advance\vsize by -\@extrafoot
+ %
+ % Bugfix, Version 2.510beta, 2016/10/11:
+ % We're fixing a bug that was introduced by the bugfix in version
+ % 2.306beta, 2009/03/28: If the second page has a different
+ % \textheight (because of a change in either headheight or
+ % footheight between pages 1 and 2), then page 2 would use the
+ % \textheight of page 1. Pages 3 and beyond would get the correct
+ % \textheight.
+ % The original version of this set \@colroom and \vsize to the new
+ % \textheight, but that had a bug in that if a float appeared at
+ % the top of a page, there would be no notice taken of the space
+ % lost to the float, and so the text would overrun the bottom of
+ % the page.
+ % In this bugfix, we adjust \@colroom, \@colht, and \vsize in the
+ % same way that we adjust \textheight.
+ %
% 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
@@ -626,16 +935,15 @@
% We *do* need to put \@colht at the correct new value, though,
% apparently because \@colht is set near the end of the
% output routine.
- \global\@colht=\textheight
+% \global\@colht=\textheight
+%
% \global\@colroom=\textheight
% \global\vsize=\textheight
% \global\pagegoal=\textheight
\endgroup
-}
+}% @setfootheight
-
-
%---------------------------------------------------------------------
%
% *************************
@@ -1246,7 +1554,7 @@
% the last such page with AtEndDocument.
\def\numpages{\@ifundefined{exam at lastpage}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at lastpage
}% numpages
@@ -1255,50 +1563,50 @@
% so that the construction \romannumeral\numcoverpages
% won't generate an error on the first run of latex.
\def\numcoverpages{\@ifundefined{exam at lastcoverpage}%
- {0\mbox{\normalfont\bf ??}}%
+ {0\mbox{\normalfont\bfseries ??}}%
\exam at lastcoverpage
}% numpages
\def\totalnumpages{\@ifundefined{exam at totalpages}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at totalpages
}% numpages
\def\numpoints{\@ifundefined{exam at numpoints}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at numpoints
}% numpoints
\def\numbonuspoints{\@ifundefined{exam at numbonuspoints}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at numbonuspoints
}% numbonuspoints
\def\numquestions{\@ifundefined{exam at numquestions}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at numquestions
}% numquestions
\def\numparts{\@ifundefined{exam at numparts}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at numparts
}% numparts
\def\numsubparts{\@ifundefined{exam at numsubparts}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at numsubparts
}% numsubparts
\def\numsubsubparts{\@ifundefined{exam at numsubsubparts}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
\exam at numsubsubparts
}% numsubsubparts
\def\pointsofquestion#1{\@ifundefined{pointsofq@\romannumeral #1}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
{\csname pointsofq@\romannumeral #1\endcsname}%
}% pointsofquestion
\def\bonuspointsofquestion#1{\@ifundefined{bonuspointsofq@\romannumeral #1}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
{\csname bonuspointsofq@\romannumeral #1\endcsname}%
}% bonuspointsofquestion
@@ -1311,11 +1619,11 @@
% for that last page, and one of those will be undefined.
%
% \def\pointsonpage#1{\@ifundefined{pointsonpage@\romannumeral #1}%
-% {\mbox{\normalfont\bf ??}}%
+% {\mbox{\normalfont\bfseries ??}}%
% {\csname pointsonpage@\romannumeral #1\endcsname}%
% }% pointsonpage
% \def\bonuspointsonpage#1{\@ifundefined{bonuspointsonpage@\romannumeral #1}%
-% {\mbox{\normalfont\bf ??}}%
+% {\mbox{\normalfont\bfseries ??}}%
% {\csname bonuspointsonpage@\romannumeral #1\endcsname}%
% }% bonuspointsonpage
%
@@ -2125,6 +2433,18 @@
\fi
}% add at half
+% Important reminder about \ifhlfcntr at pos: Do not use it inside
+% another conditional! The construction
+% \ifhlfcntr at pos{somecounter}
+% do some stuff...
+% \fi
+% is perfectly fine as long as it's expanded, but: If it's inside
+% another conditional, and the condition is not satisfied, then it's
+% read through without expansion. In that case, TeX sees the
+% \ifhlfcntr at pos but does *not* recognize it as being part of a
+% conditional, but when it sees the concluding \fi it does recognize
+% that, and so TeX completes the outer conditional at that \fi, which
+% causes an error.
\newcounter{ifpos at cntr}
\def\ifhlfcntr at pos#1{%
% The argument must be a hlfcntr (which, of course,
@@ -3132,8 +3452,8 @@
\def\@checkqueslevel#1{%
\begingroup
- \def\@temp{#1}%
- \ifx\@temp\@queslevel
+ \def\exam at temp{#1}%
+ \ifx\exam at temp\@queslevel
% Everything's fine; do nothing.
\else
\ClassError{exam}{%
@@ -3339,10 +3659,10 @@
\def\setup at point@toks{%
% We set the token list \point at toks equal to the sequence of commands
-% needed to put \padded at point@block at the correct location, followed by the
-% tokens ``\global \point at toks={}''. The \question, \part, \subpart,
-% or \subsubpart command then adds the two tokens ``\the\point at toks''
-% to \everypar.
+% needed to put \padded at point@block at the correct location, followed
+% by the tokens ``\global \point at toks={}''. The \question, \part,
+% \subpart, or \subsubpart command then adds the two tokens
+% ``\the\point at toks'' to \everypar.
%
% Note: It is not the *contents* of \point at toks that is added to
% \everypar; just the two tokens ``\the\point at toks''. This difference
@@ -3362,6 +3682,66 @@
% tokens ``\the\point at toks'' will insert an *empty* token list, which
% will do no harm.
%
+ \if at pointstwosided
+ % Set \csname \q at label \endcsname equal to the thing
+ % that expands to the page number of the current (question or
+ % part or subpart or subsubpar; whatever it is), but do it
+ % carefully because, if we don't yet have page info, then it won't
+ % be defined:
+ \ifx\@queslevel\ques at ref
+ \def\q at label{Pg at question@\arabic{question}}
+ \else
+ \ifx\@queslevel\part at ref
+ \def\q at label{Pg at part@\arabic{question}@\arabic{partno}}
+ \else
+ \ifx\@queslevel\subpart at ref
+ \def\q at label{Pg at subpart@\arabic{question}%
+ @\arabic{partno}@\arabic{subpart}}
+ \else
+ \ifx\@queslevel\subsubpart at ref
+ \def\q at label{Pg at subsubpart@\arabic{question}%
+ @\arabic{partno}@\arabic{subpart}@\arabic{subsubpart}}
+ \else
+ \ClassError{exam}{%
+ This can't happen in function \protect\setup at point@toks
+ \MessageBreak
+ }{%
+ An unexplained error occurred in exam.cls;\MessageBreak
+ please inform the package maintainer, and send along
+ \MessageBreak
+ the LaTeX file that shows the error.\MessageBreak
+ }%
+ \fi
+ \fi
+ \fi
+ \fi
+ %
+ \expandafter\ifx \csname \q at label \endcsname\relax
+ % No page info yet; put it into the right margin
+ \@pointsinrightmargintrue
+ \@pointsinleftmarginfalse
+ \else
+ \ifodd \csname \q at label \endcsname\relax
+ \if at pointsinoutsidemargin
+ \@pointsinrightmargintrue
+ \@pointsinleftmarginfalse
+ \else
+ \@pointsinrightmarginfalse
+ \@pointsinleftmargintrue
+ \fi
+ \else
+ \if at pointsinoutsidemargin
+ \@pointsinrightmarginfalse
+ \@pointsinleftmargintrue
+ \else
+ \@pointsinrightmargintrue
+ \@pointsinleftmarginfalse
+ \fi
+ \fi
+ \fi
+ \fi
+ % That ends the \if at pointstwosided.
+ % Now we actually setup \point at toks:
\if at pointsinleftmargin
\point at toks={%
\llap{\padded at point@block
@@ -3392,8 +3772,6 @@
\fi
}% setup at point@toks
-
-
\def\droppoints{%
\leavevmode\unskip\nobreak\hfill
\rlap{\hskip\rightmargin % Defined by the list environment
@@ -3404,7 +3782,6 @@
\par
}
-
\def\droptotalpoints{%
\leavevmode\unskip\nobreak\hfill
\rlap{\hskip\rightmargin % Defined by the list environment
@@ -3476,29 +3853,55 @@
\newif\if at pointsdropped
\newif\if at pointsinleftmargin
\newif\if at pointsinrightmargin
+\newif\if at pointstwosided
+\newif\if at pointsinoutsidemargin
+
+% If we have \@pointstwosidedtrue and \@pointsinoutsidemarginfalse,
+% then the points will be printed on the inside margin (left on odd
+% numbered pages, right on even numbered pages). If we have
+% \@pointstwosidedfalse, then \if at pointsinoutsidemargin is ignored.
+
+% If we have \@pointstwosidedtrue, then both \@pointsinleftmargin and
+% \@pointsinrightmargin will be flipped back and forth, as needed, in
+% \setup at point@toks.
+
\def\pointsinleftmargin{\global\@pointsinleftmargintrue
\global\@pointsinrightmarginfalse
\global\@pointsdroppedfalse
+ \global\@pointstwosidedfalse
\gdef\pt at name{\@marginpointname}%
\gdef\bnspt at name{\@marginbonuspointname}}
\def\pointsinrightmargin{\global\@pointsinrightmargintrue
\global\@pointsinleftmarginfalse
\global\@pointsdroppedfalse
+ \global\@pointstwosidedfalse
\gdef\pt at name{\@marginpointname}%
\gdef\bnspt at name{\@marginbonuspointname}}
\def\nopointsinmargin{\global\@pointsinleftmarginfalse
\global\@pointsinrightmarginfalse
\global\@pointsdroppedfalse
+ \global\@pointstwosidedfalse
\gdef\pt at name{\@pointname}%
\gdef\bnspt at name{\@bonuspointname}}
\def\pointsdroppedatright{\global\@pointsdroppedtrue
\global\@pointsinleftmarginfalse
\global\@pointsinrightmarginfalse
+ \global\@pointstwosidedfalse
\gdef\pt at name{\@marginpointname}%
\gdef\bnspt at name{\@marginbonuspointname}}
-\let\pointsinmargin\pointsinleftmargin
-\let\nopointsinrightmargin\nopointsinmargin
-\let\nopointsinleftmargin\nopointsinmargin
+\def\pointstwosided{\global\@pointstwosidedtrue
+ \global\@pointsinoutsidemargintrue
+ \global\@pointsdroppedfalse
+ \gdef\pt at name{\@marginpointname}%
+ \gdef\bnspt at name{\@marginbonuspointname}}
+\def\pointstwosidedreversed{\global\@pointstwosidedtrue
+ \global\@pointsinoutsidemarginfalse
+ \global\@pointsdroppedfalse
+ \gdef\pt at name{\@marginpointname}%
+ \gdef\bnspt at name{\@marginbonuspointname}}
+\let\pointsinmargin=\pointsinleftmargin
+\let\nopointsinrightmargin=\nopointsinmargin
+\let\nopointsinleftmargin=\nopointsinmargin
\nopointsinmargin
@@ -3534,7 +3937,6 @@
% which confines the effects of anything here:
\gdef\bonuspoint at block{#1}%
}
-\def\thebonuspoints{\@points \@bonuspointname}
%Initialize:
\noboxedpoints
@@ -3688,6 +4090,7 @@
\settowidth{\leftmargin}{W.\hskip\labelsep\hskip 2.5em}%
\def\choice{%
\if at correctchoice
+ \color at endgroup
\endgroup
\fi
\item
@@ -3695,12 +4098,30 @@
} % choice
\def\CorrectChoice{%
\if at correctchoice
+ \color at endgroup
\endgroup
\fi
\ifprintanswers
% We can't say \choice here, because that would
% insert an \endgroup:
- \begingroup \@correctchoicetrue
+ % 2016/05/10: We say \color at begingroup in addition to
+ % \begingroup in case \CorrectChoiceEmphasis involves color
+ % and the text exactly fills the line (which would
+ % otherwise create a blank line after this choice):
+ % 2016/05/11: We leave hmode if we're in it,
+ % i.e., if there's no blank line preceding this
+ % \CorrectChoice command. (Without this, the
+ % \special created by a \color{whatever} command that might
+ % be inserted by \CorrectChoice at Emphasis would be appended
+ % to the previous \choice, which could cause an extra
+ % (blank) line to be inserted before this \CorrectChoice.)
+ % Since \par and \endgraf seem to cancel \@totalleftmargin
+ % (for reasons I don't understand), we'll do the following:
+ % Motivated by the def of \leavevmode,
+ % \def\leavevmode{\unhbox\voidb at x}
+ % we will now leave hmode (if we're in hmode):
+ \ifhmode \unskip\unskip\unvbox\voidb at x \fi
+ \begingroup \color at begingroup \@correctchoicetrue
\CorrectChoice at Emphasis
\fi
\item
@@ -3713,7 +4134,7 @@
\choiceshook
}%
}%
- {\if at correctchoice \endgroup \fi \endlist}
+ {\if at correctchoice \color at endgroup \endgroup \fi \endlist}
\newenvironment{oneparchoices}%
{%
@@ -3768,7 +4189,7 @@
\settowidth{\leftmargin}{W.\hskip\labelsep\hskip 2.5em}%
\def\choice{%
\if at correctchoice
- \endgroup
+ \color at endgroup \endgroup
\fi
\item
\do at choice@pageinfo
@@ -3775,12 +4196,29 @@
} % choice
\def\CorrectChoice{%
\if at correctchoice
- \endgroup
+ \color at endgroup \endgroup
\fi
\ifprintanswers
% We can't say \choice here, because that would
- % insert an \endgroup:
- \begingroup \@correctchoicetrue
+ % insert an \endgroup.
+ % 2016/05/10: We say \color at begingroup in addition to
+ % \begingroup in case \CorrectChoiceEmphasis involves color
+ % and the text exactly fills the line (which would
+ % otherwise create a blank line after this choice):
+ % 2016/05/11: We leave hmode if we're in it,
+ % i.e., if there's no blank line preceding this
+ % \CorrectChoice command. (Without this, the
+ % \special created by a \color{whatever} command that might
+ % be inserted by \CorrectChoice at Emphasis would be appended
+ % to the previous \choice, which could cause an extra
+ % (blank) line to be inserted before this \CorrectChoice.)
+ % Since \par and \endgraf seem to cancel \@totalleftmargin
+ % (for reasons I don't understand), we'll do the following:
+ % Motivated by the def of \leavevmode,
+ % \def\leavevmode{\unhbox\voidb at x}
+ % we will now leave hmode (if we're in hmode):
+ \ifhmode \unskip\unskip\unvbox\voidb at x \fi
+ \begingroup \color at begingroup \@correctchoicetrue
\CorrectChoice at Emphasis
\item[\checked at char]
\else
@@ -3795,7 +4233,7 @@
\checkboxeshook
}%
}%
- {\if at correctchoice \endgroup \fi \endlist}
+ {\if at correctchoice \color at endgroup \endgroup \fi \endlist}
\newenvironment{oneparcheckboxes}%
{%
@@ -3851,7 +4289,8 @@
%--------------------------------------------------------------------
% Answer Lines (for short answer questions)
-% Note: \ques at ref is also used in \item at points@pageinfo
+% Note: \ques at ref is also used in \item at points@pageinfo, and all four
+% of the following are used in \setup at point@toks
\def\ques at ref{question}
\def\part at ref{part}
@@ -3894,7 +4333,10 @@
\ifprintanswers
\ans at l~\hbox to 0pt{\hbox to \answerlinelength{\hrulefill}\hss}%
\raise \answerclearance\hbox to \answerlinelength{%
- \CorrectChoice at Emphasis \hfil #1\hss}%
+ % 2016/05/10: Added \color at begingroup and \color at endgroup:
+ \color at begingroup
+ \CorrectChoice at Emphasis \hfil #1\hss
+ \color at endgroup}%
\else
\ans at l~\hbox to \answerlinelength{\hrulefill}%
\fi
@@ -3961,9 +4403,11 @@
\setbox0 \hbox{\color at begingroup
\CorrectChoice at Emphasis \fillin at ans \color at endgroup}%
\ifdim\wd0 > #1\relax
- \hbox{\CorrectChoice at Emphasis \fillin at ans}%
+ \hbox{\color at begingroup\CorrectChoice at Emphasis \fillin at ans
+ \color at endgroup}%
\else
- \hbox to #1{\CorrectChoice at Emphasis \hfil \fillin at ans \hfil}%
+ \hbox to #1{\color at begingroup\CorrectChoice at Emphasis
+ \hfil \fillin at ans \hfil\color at endgroup}%
\fi
\endgroup
\else
@@ -4043,18 +4487,71 @@
% \setlength\linefillthickness{.1pt}
%
% This value can be changed by giving a new \setlength command.
+%
+% As of version 2.503, 2016/03/25, the lines drawn by the
+% \fillwithlines command will be drawn in color if the user has given
+% the command
+%
+% \colorfillwithlines.
+%
+% The actual drawing of the lines is now done by the command
+% \do at fillwithlines, after the \fillwithlines command decides whether
+% they will be in color. The default color is set by the command
+%
+% \definecolor{FillWithLinesColor}{gray}{0.8}
+%
+% and the color can be changed by giving a new \definecolor command.
+% You can return to black lines by giving the command
+%
+% \nocolorfillwithlines
-
\newlength\linefillheight
\newlength\linefillthickness
\setlength\linefillheight{.25in}
\setlength\linefillthickness{0.1pt}
+
+
+
+\newif\if at colorfillwithlines
+\@colorfillwithlinesfalse
+\def\colorfillwithlines{%
+ \@ifundefined{definecolor}
+ {%
+ \ClassError{exam}{%
+ You must load the color package with the command\MessageBreak
+ \space\space\protect\usepackage{color}\MessageBreak
+ in order to use the command \protect\colorfillwithlines
+ \MessageBreak
+ }{%
+ This command makes use of the package color.sty,\MessageBreak
+ and so you have to load color.sty before your\MessageBreak
+ \protect\begin{document} command.\MessageBreak
+ }%
+ }%
+ {%
+ \definecolor{FillWithLinesColor}{gray}{0.8}
+ \@colorfillwithlinestrue
+ }%
+}% \colorfillwithlines
+\def\nocolorfillwithlines{\@colorfillwithlinesfalse}
+
+\newcommand\fillwithlines[1]{%
+ \if at colorfillwithlines
+ \color at begingroup
+ \color{FillWithLinesColor}%
+ \do at fillwithlines{#1}%
+ \color at endgroup
+ \else
+ \do at fillwithlines{#1}%
+ \fi
+}% \fillwithlines
+
\newcommand\linefill{\leavevmode
\leaders\hrule height \linefillthickness \hfill\kern\z@}
-
-\def\fillwithlines#1{%
+% \do at fillwithlines is called only by \fillwithlines
+\def\do at fillwithlines#1{%
\begingroup
\ifhmode
\par
@@ -4069,7 +4566,7 @@
% no matter where on the page it happens to start:
\cleaders \copy0 \vskip #1 \hbox{}%
\endgroup
-}
+}% \do at fillwithlines
%--------------------------------------------------------------------
% \fillwithdottedlines
@@ -4093,10 +4590,64 @@
%
% This value can be changed by giving a new \setlength command.
+% As of version 2.503, 2016/03/25, the dotted lines drawn by the
+% \fillwithdottedlines command will be drawn in color if the user has
+% given the command
+%
+% \colorfillwithdottedlines.
+%
+% The actual drawing of the lines is now done by the command
+% \do at fillwithdottedlines, after the \fillwithdottedlines command
+% decides whether they will be in color. The default color is set by
+% the command
+%
+% \definecolor{FillWithDottedLinesColor}{gray}{0.8}
+%
+% and the color can be changed by giving a new \definecolor command.
+% You can return to black lines by giving the command
+%
+% \nocolorfillwithdottedlines
+
+
\newlength\dottedlinefillheight
\setlength\dottedlinefillheight{.25in}
-\def\fillwithdottedlines#1{%
+\newif\if at colorfillwithdottedlines
+\@colorfillwithdottedlinesfalse
+\def\colorfillwithdottedlines{%
+ \@ifundefined{definecolor}
+ {%
+ \ClassError{exam}{%
+ You must load the color package with the command\MessageBreak
+ \space\space\protect\usepackage{color}\MessageBreak
+ in order to use the command \protect\colorfillwithdottedlines
+ \MessageBreak
+ }{%
+ This command makes use of the package color.sty,\MessageBreak
+ and so you have to load color.sty before your\MessageBreak
+ \protect\begin{document} command.\MessageBreak
+ }%
+ }%
+ {%
+ \definecolor{FillWithDottedLinesColor}{gray}{0.8}
+ \@colorfillwithdottedlinestrue
+ }%
+}% \colorfillwithdottedlines
+\def\nocolorfillwithdottedlines{\@colorfillwithdottedlinesfalse}
+
+\newcommand\fillwithdottedlines[1]{%
+ \if at colorfillwithdottedlines
+ \color at begingroup
+ \color{FillWithDottedLinesColor}%
+ \do at fillwithdottedlines{#1}%
+ \color at endgroup
+ \else
+ \do at fillwithdottedlines{#1}%
+ \fi
+}% \fillwithdottedlines
+
+% \do at fillwithdottedlines is called only by \fillwithdottedlines
+\def\do at fillwithdottedlines#1{%
\begingroup
\ifhmode
\par
@@ -4111,7 +4662,7 @@
% no matter where on the page it happens to start:
\cleaders \copy0 \vskip #1 \hbox{}%
\endgroup
-}% fillwithdottedlines
+}% \do at fillwithdottedlines
%--------------------------------------------------------------------
% \fillwithgrid
@@ -4261,7 +4812,26 @@
\newlength\minboxheight
\setlength\minboxheight{.1in}
+
+% As of version 2.502, 2016/03/23, the frame drawn by the
+% \makeemptybox command will be drawn in color if the user has given
+% the command \colorsolutionboxes. The actual drawing of the box is
+% now done by the command \do at emptybox, after the \makeemptybox
+% command decides whether it will be in color.
+
\newcommand\makeemptybox[1]{%
+ \if at colorsolutionboxes
+ \color at begingroup
+ \color{SolutionBoxColor}%
+ \do at emptybox{#1}%
+ \color at endgroup
+ \else
+ \do at emptybox{#1}%
+ \fi
+}
+
+% The command \do at emptybox is called only by \makeemptybox.
+\newcommand\do at emptybox[1]{%
\par
\hbox to \hsize{\hskip\@totalleftmargin \leaders\hrule\hfill}%
\nointerlineskip
@@ -4476,16 +5046,45 @@
\cvsword{Score}
\cvtword{Total:}
-
-% The only commands here accessible to the user are \gradetable,
-% \bonusgradetable, \combinedgradetable, \pointtable,
-% \bonuspointtable, \combinedpointtable, \partialgradetable,
+% Before we created multirow and multicolumn tables, he only commands
+% here accessible to the user were \gradetable, \bonusgradetable,
+% \combinedgradetable, \pointtable, \bonuspointtable,
+% \combinedpointtable, \partialgradetable,
% \partialbonusgradetable, \partialcombinedtable, \partialpointtable,
% \partialbonuspointtable, \partialcombinedpointtable,
% \begingradingrange, \endgradingrange, \pointsinrange,
% \bonuspointsinrange, \firstqinrange, \lastqinrange, and
-% \numqinrange.
+% \numqinrange. The new user commands are
+%
+% \def\multirowgradetable
+% \def\multirowpointtable
+% \def\multirowbonusgradetable
+% \def\multirowbonuspointtable
+% \def\multirowcombinedgradetable
+% \def\multirowcombinedpointtable
+%
+% \def\multirowpartialgradetable
+% \def\multirowpartialpointtable
+% \def\multirowpartialbonusgradetable
+% \def\multirowpartialbonuspointtable
+% \def\multirowpartialcombinedgradetable
+% \def\multirowpartialcombinedpointtable
+%
+% \def\multicolumngradetable
+% \def\multicolumnpointtable
+% \def\multicolumnbonusgradetable
+% \def\multicolumnbonuspointtable
+% \def\multicolumncombinedgradetable
+% \def\multicolumncombinedpointtable
+%
+% \def\multicolumnpartialgradetable
+% \def\multicolumnpartialpointtable
+% \def\multicolumnpartialbonusgradetable
+% \def\multicolumnpartialbonuspointtable
+% \def\multicolumnpartialcombinedgradetable
+% \def\multicolumnpartialcombinedpointtable
+
% The possibilities are
% \gradetable[v][questions]
@@ -4559,7 +5158,36 @@
% \numqinrange{whatever}
%
% where ``whatever'' is a label chosen by the user.
+%
+% \def\multirowgradetable{numcols}[questions or pages]
+% \def\multirowpointtable{numcols}[questions or pages]
+% \def\multirowbonusgradetable{numcols}[questions or pages]
+% \def\multirowbonuspointtable{numcols}[questions or pages]
+% \def\multirowcombinedgradetable{numcols}[questions or pages]
+% \def\multirowcombinedpointtable{numcols}[questions or pages]
+%
+% \def\multirowpartialgradetable{numcols}{rangename}[questions or pages]
+% \def\multirowpartialpointtable{numcols}{rangename}[questions or pages]
+% \def\multirowpartialbonusgradetable{numcols}{rangename}[questions or pages]
+% \def\multirowpartialbonuspointtable{numcols}{rangename}[questions or pages]
+% \def\multirowpartialcombinedgradetable{numcols}{rangename}[questions or pages]
+% \def\multirowpartialcombinedpointtable{numcols}{rangename}[questions or pages]
+%
+% \def\multicolumngradetable{numrows}[questions or pages]
+% \def\multicolumnpointtable{numrows}[questions or pages]
+% \def\multicolumnbonusgradetable{numrows}[questions or pages]
+% \def\multicolumnbonuspointtable{numrows}[questions or pages]
+% \def\multicolumncombinedgradetable{numrows}[questions or pages]
+% \def\multicolumncombinedpointtable{numrows}[questions or pages]
+% \def\multicolumnpartialgradetable{numrows}{rangename}[questions or pages]
+% \def\multicolumnpartialpointtable{numrows}{rangename}[questions or pages]
+% \def\multicolumnpartialbonusgradetable{numrows}{rangename}[questions or pages]
+% \def\multicolumnpartialbonuspointtable{numrows}{rangename}[questions or pages]
+% \def\multicolumnpartialcombinedgradetable{numrows}{rangename}[questions or pages]
+% \def\multicolumnpartialcombinedpointtable{numrows}{rangename}[questions or pages]
+
+
% If one or both optional arguments are omitted, the defaults are
% `[v]' and `[questions]'.
@@ -4573,8 +5201,9 @@
% \partialcombinedpointtable:
\newif\if at partial
-% \@combinedtrue means we're doing \combinedgradetable
-% or \combinedpointtable:
+% \@combinedtrue means we're doing \combinedgradetable,
+% \combinedpointtable, \partialcombinedgradetable, or
+% \partialcombinedpointtable:
\newif\if at combined
% It's OK to use the counter num at cols as a scratch counter
@@ -4606,8 +5235,6 @@
}% endgradingrange
-
-
% Now that grading tables may be for only part of the exam,
% we need the counter tbl at points to add up the total points
% for the questions (or pages) that appear on the table:
@@ -4617,7 +5244,249 @@
% points for the questions (or pages) that appear on the table:
\new at hlfcntr{tbl at bonuspoints}
+%--------------------------------------------------------------------
+% multirow tables, non-partial:
+\def\multirowgradetable#1{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowpointtable#1{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowbonusgradetable#1{%
+ \@scorestrue
+ \@bonustrue
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowbonuspointtable#1{%
+ \@scoresfalse
+ \@bonustrue
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowcombinedgradetable#1{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialfalse
+ \@combinedtrue
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowcombinedpointtable#1{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialfalse
+ \@combinedtrue
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+%--------------------------------------------------------------------
+% multirow tables, partial:
+
+\def\multirowpartialgradetable#1#2{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowpartialpointtable#1#2{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowpartialbonusgradetable#1#2{%
+ \@scorestrue
+ \@bonustrue
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowpartialbonuspointtable#1#2{%
+ \@scoresfalse
+ \@bonustrue
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowpartialcombinedgradetable#1#2{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialtrue
+ \@combinedtrue
+ \def\tbl at range{#2}%
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+\def\multirowpartialcombinedpointtable#1#2{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialtrue
+ \@combinedtrue
+ \def\tbl at range{#2}%
+ \setcounter{num at rows}{#1}%
+ \i at gtable[h]%
+}
+
+%--------------------------------------------------------------------
+% multicolumn tables, non-partial:
+
+\def\multicolumngradetable#1{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnpointtable#1{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnbonusgradetable#1{%
+ \@scorestrue
+ \@bonustrue
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnbonuspointtable#1{%
+ \@scoresfalse
+ \@bonustrue
+ \@partialfalse
+ \@combinedfalse
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumncombinedgradetable#1{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialfalse
+ \@combinedtrue
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumncombinedpointtable#1{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialfalse
+ \@combinedtrue
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+%--------------------------------------------------------------------
+% multicolumn tables, partial:
+
+\def\multicolumnpartialgradetable#1#2{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnpartialpointtable#1#2{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnpartialbonusgradetable#1#2{%
+ \@scorestrue
+ \@bonustrue
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnpartialbonuspointtable#1#2{%
+ \@scoresfalse
+ \@bonustrue
+ \@partialtrue
+ \@combinedfalse
+ \def\tbl at range{#2}%
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnpartialcombinedgradetable#1#2{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialtrue
+ \@combinedtrue
+ \def\tbl at range{#2}%
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+\def\multicolumnpartialcombinedpointtable#1#2{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialtrue
+ \@combinedtrue
+ \def\tbl at range{#2}%
+ \setcounter{num at cols}{#1}%
+ \i at gtable[v]%
+}
+
+%--------------------------------------------------------------------
+% partial single row (and column) tables:
+
\def\partialgradetable#1{%
\@scorestrue
\@bonusfalse
@@ -4624,6 +5493,12 @@
\@partialtrue
\@combinedfalse
\def\tbl at range{#1}%
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4636,6 +5511,12 @@
\@partialtrue
\@combinedfalse
\def\tbl at range{#1}%
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4648,6 +5529,12 @@
\@partialtrue
\@combinedtrue
\def\tbl at range{#1}%
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4660,6 +5547,12 @@
\@partialtrue
\@combinedfalse
\def\tbl at range{#1}%
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4672,6 +5565,12 @@
\@partialtrue
\@combinedfalse
\def\tbl at range{#1}%
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4684,6 +5583,12 @@
\@partialtrue
\@combinedtrue
\def\tbl at range{#1}%
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4691,6 +5596,7 @@
}% partialcombinedpointtable
%--------------------------------------------------------------------
+% single row (and column) tables, non-partial:
\def\gradetable{%
\@scorestrue
@@ -4697,6 +5603,12 @@
\@bonusfalse
\@partialfalse
\@combinedfalse
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4708,6 +5620,12 @@
\@bonustrue
\@partialfalse
\@combinedfalse
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4719,6 +5637,12 @@
\@bonusfalse
\@partialfalse
\@combinedtrue
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4730,6 +5654,12 @@
\@bonusfalse
\@partialfalse
\@combinedfalse
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4741,6 +5671,12 @@
\@bonustrue
\@partialfalse
\@combinedfalse
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4752,6 +5688,12 @@
\@bonusfalse
\@partialfalse
\@combinedtrue
+ % We don't yet know if the table is vertical or horizontal, and so
+ % we don't know if we need to set num at cols or num at rows. We'll set
+ % them both, and we'll later on just ignore the value of the one
+ % that we didn't need to set here:
+ \setcounter{num at cols}{1}%
+ \setcounter{num at rows}{1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4764,7 +5706,7 @@
% (the defaults being [v] and [questions]) and then make sure
% that the user said \addpoints and that this isn't the
% first run of LaTeX.
-% \do at table then branches, depending on whether the user
+% \find at p@or at q@range then branches, depending on whether the user
% selected [questions] or [pages].
\def\i at gtable[#1]{%
@@ -4774,10 +5716,11 @@
\@ifnextchar[{\ii at gtable{#1}}{\ii at gtable{#1}[questions]}%
}
\def\ii at gtable#1[#2]{%
+ % We get here from \i at gtable.
% We make sure the user said \addpoints, and then make sure
% that this isn't the first run of LaTeX (by checking that
% \exam at numpoints is defined). If both of those are OK,
- % we go on to \do at table to see whether we're doing a table
+ % we go to \find at p@or at q@range to see whether we're doing a table
% indexed by questions or by pages.
\if at addpoints
\@ifundefined{exam at numpoints}%
@@ -4788,7 +5731,7 @@
}%
\fbox{Run \LaTeX{} again to produce the table}%
}%
- {\do at table{#1}{#2}}%
+ {\find at p@or at q@range{#1}{#2}}%
\else
\ClassError{exam}{%
You must give the command \protect\addpoints\MessageBreak
@@ -4801,46 +5744,50 @@
\fi
}% ii at gtable
-
\def\@questionsref{questions}
\def\@pagesref{pages}
-\def\do at table#1#2{%
- % The first argument is ``v'' or ``h'';
- % the second argument is ``questions'' or ``pages''.
+\def\find at p@or at q@range#1#2{%
+ % We get here from \ii at gtable.
+ % The first argument should be ``v'' or ``h'';
+ % the second argument should be ``questions'' or ``pages''.
% See whether we're doing a table indexed by
- % questions or by pages:
- \begingroup % avoid trouble from using \@temp
- \def\@temp{#2}%
- \ifx\@temp\@questionsref
+ % questions (in which case we go to \find at qrange) or by pages (in
+ % which case we go to \find at prange):
+ \begingroup
+ % We've begun a group that will contain the construction of the
+ % table, to confine the effect of any \def's that we use.
+ \def\exam at temp{#2}%
+ \ifx\exam at temp\@questionsref
+ \tbl at pgsfalse
\find at qrange{#1}%
\else
- \ifx\@temp\@pagesref
+ \ifx\exam at temp\@pagesref
+ \tbl at pgstrue
\find at prange{#1}%
\else
\ClassError{exam}{%
- The second optional argument to a\MessageBreak
- \space\space grade table or point table command\MessageBreak
- \space \space must be either `questions' or
- `pages',\MessageBreak
- \space\space not `#2'.\MessageBreak
+ Grade and point tables can be indexed\MessageBreak
+ \space\space by either `questions' or `pages',\MessageBreak
+ \space\space but not by `#2'.\MessageBreak
}{%
Grade tables and point tables can be indexed by questions or
pages;\MessageBreak
\space\space for others, you're on your own.\MessageBreak
}%
- \fbox{Error: grade or point table: Invalid second
- optional argument `#2'.}%
+ \fbox{\textbf{Error:} grade or point table: Invalid argument
+ `#2' must be `questions' or `pages'.}%
\fi
\fi
\endgroup
-}% do at table
+}% find at p@or at q@range
-
+% \range at undefined can be called from either \find at qrange or
+% \find at prange
\def\range at undefined{%
\fbox{Warning: grading range `\tbl at range ' not defined;
run \LaTeX{} again.}%
\ClassWarning{exam}{%
- Grading range `\tbl at range ' not defined.\MessageBreak
+ Grading range `\tbl at range' not defined.\MessageBreak
\space\space Run LaTeX again to produce the table.\MessageBreak
}%
}% range at undefined
@@ -4850,16 +5797,18 @@
%--------------------------------------------------------------------
% Grade and point tables indexed by question numbers:
-% We get to \find at qrange if we know we're doing a table indexed
-% by question numbers. The argument is either ``v'' or ``h''.
-% If we're not doing a partial table, then \find at qrange sets
-% \tbl at firstq to 1 and \tbl at lastq to \numquestions. Otherwise,
-% \find at qrange makes sure the grading range is defined and that
-% its last question isn't before its first question.
-% \find at qrange then calls \@tblquestions, passing along the argument
-% that is either ``v'' or ``h''.
+% When we get to \find at qrange, we know we're doing a table indexed by
+% question numbers and that this is not the first run of latex. The
+% argument is either ``v'' or ``h''. If we're not doing a partial
+% table, then \find at qrange sets \tbl at firstq and \first at pq@index to 1
+% and \tbl at lastq and \last at pq@index to \numquestions. Otherwise,
+% \find at qrange makes sure the grading range is defined and that its
+% last question isn't before its first question. \find at qrange then
+% calls \tbl at v@or at h, passing along the argument that is either ``v''
+% or ``h''.
\def\find at qrange#1{%
+ % We get here from \find at p@or at q@range.
% We're doing a table indexed by question numbers.
\if at partial
\@ifundefined{range@\tbl at range @firstq}%
@@ -4874,12 +5823,14 @@
{%
\edef\tbl at firstq{\csname range@\tbl at range @firstq\endcsname}%
\edef\tbl at lastq{\csname range@\tbl at range @lastq\endcsname}%
+ \let\first at pq@index=\tbl at firstq
+ \let\last at pq@index=\tbl at lastq
% Check that firstq precedes or equals lastq:
\ifnum \tbl at firstq > \tbl at lastq\relax
- \fbox{Error: Grading Range `\tbl at range ':
+ \fbox{\textbf{Error:} Grading Range `\tbl at range':
Last question precedes first question.}%
\ClassError{exam}{%
- In grading range `\tbl at range ',
+ In grading range `\tbl at range',
the last question\MessageBreak
\space\space comes before the first question.\MessageBreak
}{%
@@ -4888,466 +5839,54 @@
least one question.\MessageBreak
}%
\else
- \@tblquestions{#1}%
+ \tbl at v@or at h{#1}%
\fi
}%
}%
\else
\def\tbl at firstq{1}%
+ \let\first at pq@index=\tbl at firstq
% \numquestions is always defined, even if this is the first
% run of LaTeX and \exam at numquestions isn't defined.
% If it's the first run of LaTeX, then its value isn't useful,
% but it's never used until a later run (when its value is useful).
\def\tbl at lastq{\numquestions}%
- \@tblquestions{#1}%
+ \let\last at pq@index=\tbl at lastq
+ \tbl at v@or at h{#1}%
\fi
}% find at qrange
-\def\@tblquestions#1{%
- % \tbl at firstq and \tbl at lastq have already been set.
- % The argument is either ``v'' or ``h', and we branch accordingly.
- \if v#1%
- \@vtblquestions
+\def\@vref{v}
+\def\@href{h}
+\def\tbl at v@or at h#1{%
+ % \first at pq@index=\tbl at firstq or \tbl at firstp and
+ % \last at pq@index=\tbl at lastq or \tbl at lastp have already been set.
+ % The argument should be either `v' or `h', and we branch
+ % accordingly.
+ \def\exam at temp{#1}%
+ \ifx\exam at temp\@vref
+ \check at num@cols at v
\else
- \if h#1%
- \@htblquestions
+ \ifx\exam at temp\@href
+ \check at num@rows at h
\else
\ClassError{exam}{%
- The first optional argument to \protect\gradetable,\MessageBreak
- \space\space \protect\bonusgradetable,
- \protect\pointtable, or\MessageBreak
- \space\space \protect\bonuspointtable
- \space must be either `h' or `v'\MessageBreak
+ Grade or point table: the argument `#1'\MessageBreak
+ \space\space must be `v' or `h'.
+ \MessageBreak
}{%
- Grade tables and point tables can be either horizontal or
- vertical;\MessageBreak
+ Grade tables and point tables can be either vertical or
+ horizontal;\MessageBreak
\space\space no diagonals allowed.\MessageBreak
}%
- \if at scores
- \if at bonus
- \fbox{Error: bonusgradetable: Invalid first optional argument
- `#1'.}%
- \else
- \fbox{Error: gradetable: Invalid first optional argument
- `#1'.}%
- \fi
- \else
- \if at bonus
- \fbox{Error: bonuspointtable: Invalid first optional argument
- `#1'.}%
- \else
- \fbox{Error: pointtable: Invalid first optional argument
- `#1'.}%
- \fi
- \fi
+ \fbox{\textbf{Error:} grade or point table: Invalid argument
+ `#1' must be `v' or `h'.}%
\fi
\fi
-}% @tblquestions
+}% tbl at v@or at h
%--------------------------------------------------------------------
-% Vertical, indexed by question numbers:
-
-\def\@vtblquestions{%
- % The table is vertical and indexed by question numbers.
- % The question range has already been determined.
- % Branch according to whether it's bonus, non-bonus, or combined,
- % and gradetable or pointtable:
- \begingroup
- % Save the current value of question in @iterator, so that
- % we can restore it after doing the table:
- \setcounter{@iterator}{\value{question}}%
- \renewcommand\arraystretch{\@gtblstretch}%
- \if at bonus
- \if at scores
- \@bvgrdtblquestions
- \else
- \@bvpttblquestions
- \fi
- \else
- \if at combined
- \if at scores
- \@cvgrdtblquestions
- \else
- \@cvpttblquestions
- \fi
- \else
- \if at scores
- \@vgrdtblquestions
- \else
- \@vpttblquestions
- \fi
- \fi
- \fi
- % Restore the saved value of question:
- \setcounter{question}{\value{@iterator}}%
- \endgroup
-}% @vtblquestions
-
-\def\@cvgrdtblquestions{%
- % Vertical combined gradetable, indexed by questions
- \set at hlfcntr{tbl at points}{0}%
- \set at hlfcntr{tbl at bonuspoints}{0}%
- \begin{tabular}{|c|c|c|c|}
- \hline
- {\@cvqword}& {\@cvpword}& {\@cvbpword}& {\@cvsword}\\
- \hline
- \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at cvloop
- {\@cvtword}& \prt at tablepoints&
- \prt at tablebonuspoints&
- \hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
-}
-\def\do at cvloop{%
- % \do at cvloop is used by \@cvgrdtblquestions
- \addtocounter{question}{1}%
- \ref{question@\arabic{question}} &
- \pointsofquestion{\arabic{question}}&
- \bonuspointsofquestion{\arabic{question}}&\\
- \hline
- \@ifundefined{pointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at points}
- {\csname pointsofq@\romannumeral \c at question\endcsname}}%
- \@ifundefined{bonuspointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at bonuspoints}
- {\csname bonuspointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at cvloop=\do at cvloop
- \else
- \let\next at cvloop=\relax
- \fi
- \next at cvloop
-}% do at cvloop
-
-
-\def\@cvpttblquestions{%
- % Vertical combined pointtable, indexed by questions
- \set at hlfcntr{tbl at points}{0}%
- \set at hlfcntr{tbl at bonuspoints}{0}%
- \begin{tabular}{|c|c|c|}
- \hline
- {\@cvqword}& {\@cvpword}& {\@cvbpword}\\
- \hline
- \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at cvptloop
- {\@cvtword}& \prt at tablepoints&
- \prt at tablebonuspoints\\
- \hline
- \end{tabular}%
-}
-\def\do at cvptloop{%
- % \do at cvptloop is used by \@cvpttblquestions
- \addtocounter{question}{1}%
- \ref{question@\arabic{question}} &
- \pointsofquestion{\arabic{question}}&
- \bonuspointsofquestion{\arabic{question}}\\
- \hline
- \@ifundefined{pointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at points}
- {\csname pointsofq@\romannumeral \c at question\endcsname}}%
- \@ifundefined{bonuspointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at bonuspoints}
- {\csname bonuspointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at cvptloop=\do at cvptloop
- \else
- \let\next at cvptloop=\relax
- \fi
- \next at cvptloop
-}% do at cvptloop
-
-
-\def\@bvgrdtblquestions{%
- % Vertical bonus gradetable, indexed by questions:
- \set at hlfcntr{tbl at bonuspoints}{0}%
- \begin{tabular}{|c|c|c|}
- \hline
- {\@bvqword}& {\@bvpword}& {\@bvsword}\\
- \hline
- \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at bvloop
- {\@bvtword}& \prt at tablebonuspoints&\hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
-}% @bvgrdtblquestions
-\def\do at bvloop{%
- % \do at bvloop is used by \@bvgrdtblquestions
- \addtocounter{question}{1}%
- \ref{question@\arabic{question}} &
- \bonuspointsofquestion{\arabic{question}}&\\
- \hline
- \@ifundefined{bonuspointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at bonuspoints}
- {\csname bonuspointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at bvloop=\do at bvloop
- \else
- \let\next at bvloop=\relax
- \fi
- \next at bvloop
-}% do at bvloop
-
-
-\def\@bvpttblquestions{%
- % Vertical bonus point table, indexed by questions:
- \set at hlfcntr{tbl at bonuspoints}{0}%
- \begin{tabular}{|c|c|}
- \hline
- {\@bvqword}& {\@bvpword}\\
- \hline
- \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at bvptloop
- {\@bvtword}& \prt at tablebonuspoints\\
- \hline
- \end{tabular}%
-}% @bvpttblquestions
-\def\do at bvptloop{%
- % \do at bvptloop is used by \@bvpttblquestions
- \addtocounter{question}{1}%
- \ref{question@\arabic{question}} &
- \bonuspointsofquestion{\arabic{question}}\\
- \hline
- \@ifundefined{bonuspointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at bonuspoints}
- {\csname bonuspointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at bvptloop=\do at bvptloop
- \else
- \let\next at bvptloop=\relax
- \fi
- \next at bvptloop
-}% do at bvptloop
-
-\def\@vgrdtblquestions{%
- % Vertical non-bonus grade table, indexed by questions:
- \set at hlfcntr{tbl at points}{0}%
- \begin{tabular}{|c|c|c|}
- \hline
- {\@vqword}& {\@vpword}& {\@vsword}\\
- \hline
- \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at vloop
- {\@vtword}& \prt at tablepoints&\hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
-}% @vgrdtblquestions
-\def\do at vloop{%
- % \do at vloop is used by \@vgrdtblquestions
- \addtocounter{question}{1}%
- \ref{question@\arabic{question}} &
- \pointsofquestion{\arabic{question}}&\\
- \hline
- \@ifundefined{pointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at points}
- {\csname pointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at vloop=\do at vloop
- \else
- \let\next at vloop=\relax
- \fi
- \next at vloop
-}% do at vloop
-
-
-\def\@vpttblquestions{%
- % Vertical non-bonus point table, indexed by questions:
- \set at hlfcntr{tbl at points}{0}%
- \begin{tabular}{|c|c|}
- \hline
- {\@vqword}& {\@vpword}\\
- \hline
- \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at vptloop
- {\@vtword}& \prt at tablepoints\\
- \hline
- \end{tabular}%
-}% @vpttblquestions
-\def\do at vptloop{%
- % \do at vptloop is used by \@vpttblquestions
- \addtocounter{question}{1}%
- \ref{question@\arabic{question}} &
- \pointsofquestion{\arabic{question}}\\
- \hline
- \@ifundefined{pointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at points}
- {\csname pointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at vptloop=\do at vptloop
- \else
- \let\next at vptloop=\relax
- \fi
- \next at vptloop
-}% do at vptloop
-
-
%--------------------------------------------------------------------
-% Horizontal, indexed by question numbers:
-
-\def\@htblquestions{%
- % We get here from \@tblquestions.
- % The table is horizontal and indexed by question numbers.
- % The question range has already been determined.
- % Set num at cols equal to the number of questions on the table, and
- % do either bonus, combined, or non-bonus table, in each case
- % putting in a line for scores only if it's a gradetable:
- \@ifundefined{exam at numquestions}%
- {}%
- {%
- \setcounter{num at cols}{\tbl at lastq}%
- \addtocounter{num at cols}{-\tbl at firstq}%
- \addtocounter{num at cols}{1}%
- }%
- % Do either bonus, combined, or non-bonus table. In each case, put
- % in a line for scores if it's a gradetable:
- \begingroup
- % Save the current value of question in @iterator, so that
- % we can restore it after doing the table:
- \setcounter{@iterator}{\value{question}}%
- \renewcommand\arraystretch{\@gtblstretch}%
- \if at bonus
- % It's a horizontal bonus table, by questions:
- \begin{tabular}{|l|*{\thenum at cols}{c|}c|}
- \hline
- {\@bhqword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at qnumloop
- {\@bhtword}\\
- \hline
- \set at hlfcntr{tbl at bonuspoints}{0}%
- {\@bhpword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at bptloop
- \prt at tablebonuspoints\\
- \hline
- % If it's a grade table, add in the score line:
- \if at scores
- {\@bhsword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at sloop
- \\
- \hline
- \fi
- \end{tabular}%
- \else
- \if at combined
- % It's a horizontal combined table, by questions:
- \begin{tabular}{|l|*{\thenum at cols}{c|}c|}
- \hline
- {\@chqword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at qnumloop
- {\@chtword}\\
- \hline
- \set at hlfcntr{tbl at points}{0}%
- {\@chpword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at ptloop
- \prt at tablepoints\\
- \hline
- \set at hlfcntr{tbl at bonuspoints}{0}%
- {\@chbpword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at bptloop
- \prt at tablebonuspoints\\
- \hline
- % If it's a grade table, add in the score line:
- \if at scores
- {\@chsword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at sloop
- \\
- \hline
- \fi
- \end{tabular}%
- \else
- % Horizontal non-bonus table, indexed by question number:
- \set at hlfcntr{tbl at points}{0}%
- \begin{tabular}{|l|*{\thenum at cols}{c|}c|}
- \hline
- {\@hqword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at qnumloop
- {\@htword}\\
- \hline
- {\@hpword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at ptloop
- \prt at tablepoints\\
- \hline
- % If it's a grade table, add in the score line:
- \if at scores
- {\@hsword}& \setcounter{question}{\tbl at firstq}%
- \addtocounter{question}{-1}\do at sloop
- \\
- \hline
- \fi
- \end{tabular}%
- \fi
- \fi
- % Restore the saved value of question:
- \setcounter{question}{\value{@iterator}}%
- \endgroup
-}% @htblquestions
-
-
-% \do at qnumloop and \do at sloop are used by non-bonus,
-% combined, and bonus tables:
-\def\do at qnumloop{%
- \addtocounter{question}{1}%
- \ref{question@\arabic{question}}&
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at qnloop=\do at qnumloop
- \else
- \let\next at qnloop=\relax
- \fi
- \next at qnloop
-}% do at qnumloop
-\def\do at sloop{%
- \addtocounter{question}{1}%
- \hbox to \@cellwidth{\hfill}&
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at sloop=\do at sloop
- \else
- \let\next at sloop=\relax
- \fi
- \next at sloop
-}% do at sloop
-
-% \do at ptloop is used by combined and non-bonus tables:
-\def\do at ptloop{%
- \addtocounter{question}{1}%
- \pointsofquestion{\arabic{question}}&
- \@ifundefined{pointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at points}
- {\csname pointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at ptloop=\do at ptloop
- \else
- \let\next at ptloop=\relax
- \fi
- \next at ptloop
-}% do at ptloop
-
-% \do at bptloop is used by bonus and combined tables:
-\def\do at bptloop{%
- \addtocounter{question}{1}%
- \bonuspointsofquestion{\arabic{question}}&
- \@ifundefined{bonuspointsofq@\romannumeral \c at question}%
- {}%
- {\addto at hlfcntr{tbl at bonuspoints}
- {\csname bonuspointsofq@\romannumeral \c at question\endcsname}}%
- \ifnum \value{question} < \tbl at lastq\relax
- \let\next at bptloop=\do at bptloop
- \else
- \let\next at bptloop=\relax
- \fi
- \next at bptloop
-}% do at bptloop
-
-
-%--------------------------------------------------------------------
-%--------------------------------------------------------------------
% Grade and point tables indexed by page numbers:
@@ -5374,18 +5913,23 @@
% \find at prange makes sure the grading range is defined and that its
% last page isn't before its first page (if it's a partial table). In
% any case, it then sets \tbl at firstp and \tbl at lastp, and calls
-% \@tblpages.
+% \check at secondrun.
\def\find at prange#1{%
+ % We get here from \find at p@or at q@range.
% We're doing a table indexed by pages.
% The argument is either ``v'' or ``h''.
- % After determining the first and last page of the range, we
- % call \@tblpages, passing it that argument (i.e., we say
- % \@tblpages{#1}).
- % If not a partial table, we set \tbl at firstp to 1 and \tbl at lastp to
+ % We first determine the first and last page of the range, storing
+ % those in \first at pq@index=\tbl at firstp and
+ % \last at pq@index=\tbl at lastp. If not a partial table, we set
+ % \first at pq@index=\tbl at firstp to 1 and \last at pq@index=\tbl at lastp to
% the last page with the appropriate points (and so if it's a
% combined table, it's the last page to have either bonus or
% non-bonus points).
+ % We then call \check at secondrun, passing it the argument that we
+ % received (i.e., we say \check at secondrun{#1}) to make sure
+ % we've done at least two runs of latex (so that we'll have the
+ % information we need about which pages have points on them).
\if at partial
\@ifundefined{range@\tbl at range @firstp}%
{%
@@ -5399,12 +5943,14 @@
{%
\edef\tbl at firstp{\csname range@\tbl at range @firstp\endcsname}%
\edef\tbl at lastp{\csname range@\tbl at range @lastp\endcsname}%
+ \let\first at pq@index=\tbl at firstp
+ \let\last at pq@index=\tbl at lastp
% Check that firstp precedes or equals lastp:
\ifnum \tbl at firstp > \tbl at lastp\relax
- \fbox{Error: Grading Range `\tbl at range ':
+ \fbox{\textbf{Error:} Grading Range `\tbl at range ':
Last page precedes first page.}%
\ClassError{exam}{%
- In grading range `\tbl at range ', the last page\MessageBreak
+ In grading range `\tbl at range', the last page\MessageBreak
\space\space comes before the first page.\MessageBreak
}{%
\string\begingradingrange \space must precede
@@ -5411,792 +5957,1503 @@
\string\endgradingrange.\MessageBreak
}%
\else
- \@tblpages{#1}%
+ \check at secondrun{#1}%
\fi
}%
}%
\else
+ % It's not a partial table:
\def\tbl at firstp{1}%
- % \tbl at lastp isn't used on the first run of LaTeX, and
+ \let\first at pq@index=\tbl at firstp
+ % We never get here on the first run of LaTeX, and
% \lastpage at withbonuspoints is defined on the second and later runs.
\def\tbl at lastp{\lastpage at withpoints}%
+ \let\last at pq@index=\tbl at lastp
\if at bonus
\def\tbl at lastp{\lastpage at withbonuspoints}%
+ \let\last at pq@index=\tbl at lastp
\fi
\if at combined
\ifnum \lastpage at withbonuspoints > \lastpage at withpoints\relax
\def\tbl at lastp{\lastpage at withbonuspoints}%
+ \let\last at pq@index=\tbl at lastp
\fi
\fi
- \@tblpages{#1}%
+ \check at secondrun{#1}%
\fi
}% find at prange
-
-\def\@tblpages#1{%
+\def\check at secondrun#1{%
+ % The function \ii at gtable already made sure that this isn't the
+ % first run of latex. To do a table indexed by pages, though, we
+ % have to also make sure it's not the second run of latex.
% We get here from \find at prange; the argument is either ``v'' or
% ``h''.
% Check that there's enough info from the .aux file to do a page
- % indexed grade table. If so, call \@whichtblpgs{#1}:
- \@ifundefined{lastpage at withpoints}%
- {\ClassWarning{exam}{%
- You must run LaTeX twice more\MessageBreak
- \space\space to produce the table.\MessageBreak}%
- \fbox{Run \LaTeX{} twice more to produce the table}%
- }%
- {%
- \@ifundefined{pointsonpage@\romannumeral
+ % indexed grade table. If so, call \tbl at v@or at h{#1}:
+ \@ifundefined{pointsonpage@\romannumeral
\csname lastpage at withpoints\endcsname}%
+ {\@ifundefined{bonuspointsonpage@\romannumeral
+ \csname lastpage at withbonuspoints\endcsname}%
{\ClassWarning{exam}{%
- You must run LaTeX again\MessageBreak
- \space\space to produce the table.\MessageBreak}%
+ You must run LaTeX again to produce the table.\MessageBreak}%
\fbox{Run \LaTeX{} again to produce the table}%
}%
- {%
- \@whchtblpgs#1
+ {\tbl at v@or at h{#1}%
}%
}%
-}% @tblpages
+ {\tbl at v@or at h{#1}%
+ }%
+}% check at secondrun
-\def\@whchtblpgs#1{%
- % At this point, we know the table is indexed by pages.
- % It can be vertical or horizontal,
- % grade or point, and bonus or non-bonus.
- % The argument is either ``v'' or ``h''; test it, and branch:
- \if v#1%
- \@vtblpages
+%--------------------------------------------------------------------
+% Indexed by pages:
+
+% For a table indexed by pages, we need to know how many pages there
+% are with points on them. The argument to \count at pgswpts should be
+% the name of a counter; we set that counter equal to the number of
+% pages with the appropriate kind of points.
+
+\def\count at pgswpts#1{%
+ % Set the counter #1 equal to the number of pages in the range with
+ % the appropriate type of points.
+ % We're called by \@computenumcols at h and \@computenumrows at v.
+ \setcounter{#1}{0}%
+ \setcounter{@iterator}{\tbl at firstp}%
+ \addtocounter{@iterator}{-1}%
+ \if at bonus
+ \docount at pgswbpts{#1}%
\else
- \if h#1%
- \@htblpages
+ \if at combined
+ \docount at pgswcpts{#1}%
\else
- \ClassError{exam}{%
- The first optional argument to
- \protect\gradetable,\MessageBreak
- \space\space \protect\bonusgradetable,
- \protect\pointtable, or\MessageBreak
- \space\space
- \protect\bonuspointtable \space must be either `h' or
- `v'\MessageBreak
- }{%
- Grade tables and point tables can be either horizontal or
- vertical;\MessageBreak
- \space\space no diagonals allowed.\MessageBreak
- }%
- \if at scores
- \if at bonus
- \fbox{Error: bonusgradetable: Invalid first optional argument
- `#1'.}%
- \else
- \fbox{Error: gradetable: Invalid first optional argument
- `#1'.}%
- \fi
- \else
- \if at bonus
- \fbox{Error: bonuspointtable: Invalid first optional argument
- `#1'.}%
- \else
- \fbox{Error: pointtable: Invalid first optional argument
- `#1'.}%
- \fi
- \fi
+ \docount at pgswpts{#1}%
\fi
\fi
-}% \@whchtblpgs
+}% count at pgswpts
-%--------------------------------------------------------------------
-% Vertical, indexed by pages:
-
-\def\@vtblpages{%
- % We get here from \@whchtblpgs.
- % At this point, we know it's a vertical table indexed by pages.
- % It can be grade or point, and bonus, non-bonus, or combined.
- \begingroup
- \renewcommand\arraystretch{\@gtblstretch}%
- \if at bonus
- % It's vertical, bonus, by pages, either point or grade:
- \set at hlfcntr{tbl at bonuspoints}{0}%
- \if at scores
- \begin{tabular}{|c|c|c|}
- \hline
- {\@bvpgword}& {\@bvpword}& {\@bvsword}\\
- \hline
- \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\pg at bvloop
- {\@bvtword}& \prt at tablebonuspoints&
- \hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
- \else
- \begin{tabular}{|c|c|}
- \hline
- {\@bvpgword}& {\@bvpword}\\
- \hline
- \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\pg at ptbvloop
- {\@bvtword}& \prt at tablebonuspoints\\
- \hline
- \end{tabular}%
- \fi
- \else
- \if at combined
- % It's vertical, combined, by pages, either point or grade:
- \set at hlfcntr{tbl at points}{0}%
- \set at hlfcntr{tbl at bonuspoints}{0}%
- \if at scores
- % Combined gradetable, vertical, by pages:
- \begin{tabular}{|c|c|c|c|}
- \hline
- {\@cvpgword}& {\@cvpword}& {\@cvbpword}& {\@cvsword}\\
- \hline
- \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\pg at cvloop
- {\@cvtword}& \prt at tablepoints&
- \prt at tablebonuspoints&
- \hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
- \else
- % Combined pointtable, vertical, by pages:
- \begin{tabular}{|c|c|c|}
- \hline
- {\@cvpgword}& {\@cvpword}& {\@cvbpword}\\
- \hline
- \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\pg at ptcvloop
- {\@cvtword}& \prt at tablepoints&
- \prt at tablebonuspoints\\
- \hline
- \end{tabular}%
- \fi
- \else
- % It's non-bonus, either point or grade:
- \set at hlfcntr{tbl at points}{0}%
- \if at scores
- \begin{tabular}{|c|c|c|}
- \hline
- {\@vpgword}& {\@vpword}& {\@vsword}\\
- \hline
- \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\pg at vloop
- {\@vtword}& \prt at tablepoints&\hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
- \else
- \begin{tabular}{|c|c|}
- \hline
- {\@vpgword}& {\@vpword}\\
- \hline
- \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\pg at ptvloop
- {\@vtword}& \prt at tablepoints\\
- \hline
- \end{tabular}%
- \fi
- \fi
- \fi
- \endgroup
-}% @vtblpages
-
-
-% \pg at ptvloop and \pg at ptvloopline are used only by non-bonus pointtable:
-\def\pg at ptvloop{%
+\def\docount at pgswcpts#1{%
+ % Called by \count at pgswpts
+ % Count the number of pages in range with any kind of point (bonus
+ % or non-bonus):
\addtocounter{@iterator}{1}%
\set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
\ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at points}{tmp at hlfcntr}%
- \pg at ptvloopline
+ \addtocounter{#1}{1}%
+ \else
+ \check at bnsptpage{#1}%
\fi
\ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pg@ptvloop=\pg at ptvloop
+ \def\nextdocount at pgswcpts{\docount at pgswcpts{#1}}%
\else
- \let\next at pg@ptvloop=\relax
+ \let\nextdocount at pgswcpts=\relax
\fi
- \next at pg@ptvloop
-}% pg at ptvloop
-\def\pg at ptvloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstpoints at onpage@\arabic{@iterator}} &
- \pointsonpage{\the at iterator}\\
- \hline
-}% pg at ptvloopline
+ \nextdocount at pgswcpts
+}% docount at pgswcpts
+\def\check at bnsptpage#1{%
+ % We need to hide this inside of a macro because if \ifhlfcntr at pos
+ % isn't expanded (because this stuff is being skipped in the outer
+ % conditional), then TeX doesn't see the \ifnum hidden inside the
+ % \ifhlfcntr at pos, but it does see the \fi, and so it get confused.
+ \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
+ \ifhlfcntr at pos{tmp at hlfcntr}%
+ \addtocounter{#1}{1}%
+ \fi
+}% check at bnsptpage
-% \pg at vloop and \pg at vloopline are used only by non-bonus gradetable:
-\def\pg at vloop{%
+\def\docount at pgswpts#1{%
+ % Called by \count at pgswpts.
+ % Count the number of pages in range with regular points.
\addtocounter{@iterator}{1}%
\set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
\ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at points}{tmp at hlfcntr}%
- \pg at vloopline
+ \addtocounter{#1}{1}%
\fi
\ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pg@vloop=\pg at vloop
+ \def\nextdocount at pgswpts{\docount at pgswpts{#1}}%
\else
- \let\next at pg@vloop=\relax
+ \let\nextdocount at pgswpts=\relax
\fi
- \next at pg@vloop
-}% pg at vloop
-\def\pg at vloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstpoints at onpage@\arabic{@iterator}} &
- \pointsonpage{\the at iterator}&\\
- \hline
-}% pg at vloopline
+ \nextdocount at pgswpts
+}% docount at pgswpts
-% \pg at cvloop, \pg at noncvloopline, \check at bnspts, and
-% \pg at cvloopline are used only by combined gradetable:
-\def\pg at cvloop{%
+\def\docount at pgswbpts#1{%
+ % Called by \count at pgswpts
+ % Count the number of pages in range with bonus points.
\addtocounter{@iterator}{1}%
- % Add the bonus points:
\set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \add at hlfcntrtohlfcntr{tbl at bonuspoints}{tmp at hlfcntr}%
- % Add the regular points:
- \set at hlfcntr{tmp at hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
- \add at hlfcntrtohlfcntr{tbl at points}{tmp at hlfcntr}%
- % Print a line of the table, if there are points on this page:
\ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at noncvloopline
- \else
- \check at bnspts
+ \addtocounter{#1}{1}%
\fi
- % Do the tail recursion bit:
\ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pg@cvloop=\pg at cvloop
+ \def\nextdocount at pgswbpts{\docount at pgswbpts{#1}}%
\else
- \let\next at pg@cvloop=\relax
+ \let\nextdocount at pgswbpts=\relax
\fi
- \next at pg@cvloop
-}% pg at cvloop
-\def\pg at noncvloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstpoints at onpage@\arabic{@iterator}}&
- \pointsonpage{\the at iterator}&
- \bonuspointsonpage{\the at iterator}&\\
- \hline
-}% pg at noncvloopline
-\def\check at bnspts{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at cvloopline
+ \nextdocount at pgswbpts
+}% docount at pgswbpts
+
+%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+% Multirow horizontal tables, indexed by question numbers:
+
+\newcounter{pq at index}% In tables indexed by page numbers, it holds a
+% page number. In tables indexed by question numbers, it holds a
+% question number.
+
+\newcounter{pq at index@pts}% In horizontal tables, this holds either the
+% current page number or the current question number as we put the
+% point values for that page or question number into the table. In
+% vertical tables, this holds the index for the first column of the
+% current row.
+
+\newcounter{pq at index@bpts}% used to set bonus point values in
+% horizontal tables. Often used as scratch elsewhere.
+
+\def\hidden at ampersand{&}% Needed because an ampersand can't appear in
+% the replacement text of a conditional.
+
+\newif\iftbl at pgs
+% \tbl at pgstrue means a table indexed by page numbers
+% \tbl at pgsfalse means a table indexed by question numbers
+
+\newcounter{num at cols}
+\newcounter{num at rows}
+\newcounter{current at row}
+\newcounter{cols at done}% Holds the number of columns done in the
+% current row.
+
+%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+% Stuff to unify tables indexed by questions and tables indexed by
+% pages:
+
+% \first at pq@index and \last at pq@index will hold either \tbl at firstq and
+% \tbl at lastq or \tbl at firstp and \tbl at lastp.
+
+\def\increment at index#1{%
+ % If we're doing a table indexed by question numbers, we increment
+ % the counter #1.
+ % If we're doing a table indexed by page numbers,
+ % we increase the counter #1 by at least 1 to either the number of the
+ % next page containing the appropriate kind of points, or to
+ % something greater than \tbl at lastp.
+ \iftbl at pgs
+ \find at nextpagewithpoints{#1}%
+ \else
+ \addtocounter{#1}{1}%
\fi
-}% check at bnspts
-\def\pg at cvloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstbonuspoints at onpage@\arabic{@iterator}}&
- \pointsonpage{\the at iterator}&
- \bonuspointsonpage{\the at iterator}&\\
- \hline
-}% pg at cvloopline
+}% increment at index
-% \pg at ptcvloop, \pg at ptnoncvloopline, \check at ptbnspts, and
-% \pg at ptcvloopline are used only by combined pointtable:
-\def\pg at ptcvloop{%
- \addtocounter{@iterator}{1}%
- % Add the bonus points:
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \add at hlfcntrtohlfcntr{tbl at bonuspoints}{tmp at hlfcntr}%
- % Add the regular points:
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \add at hlfcntrtohlfcntr{tbl at points}{tmp at hlfcntr}%
- % Print a line of the table, if there are points on this page:
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at ptnoncvloopline
+\def\nextcolumn at index@v#1{%
+ % Used only for multicolumn tables.
+ % If we're doing a table indexed by question numbers, we increase
+ % the counter #1 by num at cols.
+ % If we're doing a table indexed by page numbers,
+ % we use \find at nextcolumnpage@v to increment the counter #1 to either
+ % the (num at rows)'th page number after #1 that contains the
+ % appropriate kind of points or to a value greater than \tbl at lastp.
+ \iftbl at pgs
+ \find at nextcolumnpage@v{#1}%
\else
- \check at ptbnspts
+ \addtocounter{#1}{\value{num at rows}}%
\fi
- % Do the tail recursion bit:
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pg@ptcvloop=\pg at ptcvloop
+}% nextcolumn at index@v
+
+\def\pointsof at index#1{%
+ \iftbl at pgs
+ \pointsonpage{\arabic{#1}}%
\else
- \let\next at pg@ptcvloop=\relax
+ \pointsofquestion{\arabic{#1}}%
\fi
- \next at pg@ptcvloop
-}% pg at ptcvloop
-\def\pg at ptnoncvloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstpoints at onpage@\arabic{@iterator}}&
- \pointsonpage{\the at iterator}&
- \bonuspointsonpage{\the at iterator}\\
- \hline
-}% pg at ptnoncvloopline
-\def\check at ptbnspts{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at ptcvloopline
+}% pointsof at index
+
+\def\bonuspointsof at index#1{%
+ \iftbl at pgs
+ \bonuspointsonpage{\arabic{#1}}%
+ \else
+ \bonuspointsofquestion{\arabic{#1}}%
\fi
-}% check at ptbnspts
-\def\pg at ptcvloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstbonuspoints at onpage@\arabic{@iterator}}&
- \pointsonpage{\the at iterator}&
- \bonuspointsonpage{\the at iterator}\\
- \hline
-}% pg at ptcvloopline
+}% bonuspointsof at index
-% \pg at bvloop and \pg at bvloopline are used only by bonus gradetable:
-\def\pg at bvloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at bonuspoints}{tmp at hlfcntr}%
- \pg at bvloopline
- \fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pg@bvloop=\pg at bvloop
+\def\refto at index#1{%
+ \iftbl at pgs
+ \if at combined
+ % Need to hide this inside of a macro:
+ \refto at comb@index{#1}%
+ \else
+ \if at bonus
+ \pageref{firstbonuspoints at onpage@\arabic{#1}}%
+ \else
+ \pageref{firstpoints at onpage@\arabic{#1}}%
+ \fi
+ \fi
\else
- \let\next at pg@bvloop=\relax
+ \ref{question@\arabic{#1}}%
\fi
- \next at pg@bvloop
-}% pg at bvloop
-\def\pg at bvloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstbonuspoints at onpage@\arabic{@iterator}} &
- \bonuspointsonpage{\the at iterator}&\\
- \hline
-}% pg at bvloopline
+}% refto at index
-% \pg at ptbvloop and \pg at ptbvloopline are used only by bonus pointtable:
-\def\pg at ptbvloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
+\def\refto at comb@index#1{%
+ % We're called only by \refto at index.
+ % We can't have the \ifhlfcntr at pos...\fi inside of another
+ % conditional, so we're hiding it in this macro.
+ \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\arabic{#1}}}%
\ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at bonuspoints}{tmp at hlfcntr}%
- \pg at ptbvloopline
+ \pageref{firstpoints at onpage@\arabic{#1}}%
+ \else
+ % In theory, there *must* be bonus points on this page, because
+ % there aren't any plain points, but there are allegedly *some*
+ % points. We're being brave and assuming that's correct, and not
+ % checking (which we'd have to hide inside a macro, because it
+ % would use \ifhlfcntr at pos):
+ \pageref{firstbonuspoints at onpage@\arabic{#1}}%
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pg@ptbvloop=\pg at ptbvloop
+}% refto at comb@index
+
+%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+% Multirow tables:
+
+
+%--------------------------------------------------------------------
+% Check that the number of rows is OK, and compute the number of
+% columns:
+
+\def\check at num@rows at h{%
+ % We get here from \tbl at v@or at h.
+ % We make sure the number of rows is a positive integer. If it
+ % is, we go on to \@computenumcols at h
+ \ifnum \value{num at rows} < 1\relax
+ \ClassError{exam}{%
+ The number of rows in a table must be positive.\MessageBreak
+ }{%
+ The number of rows must be a positive integer.\MessageBreak
+ }%
+ \fbox{\textbf{Error:} Multirow table with no rows!}%
\else
- \let\next at pg@ptbvloop=\relax
+ \@computenumcols at h
\fi
- \next at pg@ptbvloop
-}% pg at ptbvloop
-\def\pg at ptbvloopline{%
- % We still don't understand why we need to hide this inside of a
- % macro; there's some weird interaction with the \ifnum checking to
- % see if something is ``>0''; checking that something is ``=0''
- % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \pageref{firstbonuspoints at onpage@\arabic{@iterator}} &
- \bonuspointsonpage{\the at iterator}\\
- \hline
-}% pg at ptbvloopline
+}% check at num@rows at h
+\def\@computenumcols at h{%
+ % We get here from \check at num@rows at h.
+ % Compute the number of columns.
+ % First: set num at cols to one more than either (the number of pages
+ % with the appropriate type of points) or (the number of questions),
+ % to have slots for the total along with the questions:
+ \iftbl at pgs
+ \count at pgswpts{num at cols}%
+ \addtocounter{num at cols}{1}%
+ \else
+ \setcounter{num at cols}{\tbl at lastq}%
+ \addtocounter{num at cols}{-\tbl at firstq}%
+ \addtocounter{num at cols}{2}%
+ \fi
+ % Save the number of slots needed in pq at index (used for scratch), to
+ % check for truncation:
+ \setcounter{pq at index}{\value{num at cols}}%
+ % Divide the number of slots needed by num at rows:
+ \divide \csname c at num@cols\endcsname by
+ \csname c at num@rows\endcsname
+ % Division truncates: See if there was truncation.
+ % Use @iterator as a scratch counter.
+ \setcounter{@iterator}{\value{num at cols}}%
+ \multiply \csname c@@iterator\endcsname by
+ \csname c at num@rows\endcsname
+ \ifnum \value{@iterator} < \value{pq at index}\relax
+ % There was truncation; add a column to num at cols:
+ \addtocounter{num at cols}{1}%
+ \fi
+ \@multirowtable
+}% @computenumcols at h
+
%--------------------------------------------------------------------
-% Horizontal, indexed by pages:
+% Construct the actual table:
-% For a horizontal table, before we begin we need to know how many
-% pages there are with points on them:
-\newcounter{num at cols}
-\def\count at pgswpts{%
- % We're called by \@htblpages.
- % \count at pgswpts is used for horizontal
- % grade tables and point tables,
- % bonus, non-bonus, and combined.
- \setcounter{num at cols}{0}%
- \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}%
+\def\@multirowtable{%
+ % We get here from \@computenumcols at h.
+ % All multirow tables!
+ \renewcommand\arraystretch{\@gtblstretch}%
+ \set at hlfcntr{tbl at points}{0}%
+ \set at hlfcntr{tbl at bonuspoints}{0}%
+ \setcounter{pq at index}{\first at pq@index}%
+ \addtocounter{pq at index}{-1}%
+ \setcounter{pq at index@pts}{\value{pq at index}}%
+ \setcounter{pq at index@bpts}{\value{pq at index}}%
+ \setcounter{current at row}{0}%
+ \begin{tabular}{|l|*{\value{num at cols}}{c|}}
+ \hline
+ \if at combined
+ \do at comblines@h
+ \else
+ \do at lines@h
+ \fi
+}% @multirowtable
+
+
+\def\do at lines@h{%
+ % Called only by \@multirowtable.
+ % It's either bonus or regular, but not combined:
+ \addtocounter{current at row}{1}% Set to the number of the current row
+ \iftbl at pgs
+ \if at bonus
+ \@bhpgword
+ \else
+ \@hpgword
+ \fi
+ \else
+ \if at bonus
+ \@bhqword
+ \else
+ \@hqword
+ \fi
+ \fi
+ \setcounter{cols at done}{0}%
+ \do at pq@indexloop at h
+ % When we finish \do at pq@indexloop at h, either we've finished a
+ % complete row of page numbers (or questions), or we've done all
+ % the page numbers (or questions) through \last at pq@index, or both:
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ % We've inserted all the page or question numbers, and there's
+ % room remaining on the current line for \@htword (or \@bhtword):
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % This is the last row; put in the total:
+ \do at htword@h
+ \else
+ % This isn't the last row. We insert (\value{num at cols} -
+ % \value{cols at done}) ampersands.
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
+ \fi
+ \fi
+ \\
+ \hline
+ % Point values go here!
+ \setcounter{cols at done}{0}%
\if at bonus
- \docount at pgswbpts
+ \@bhpword
+ \do at bptloop@h
\else
- \if at combined
- \docount at pgswcpts
+ \@hpword
+ \do at ptloop@h
+ \fi
+ % When we finish \do at ptloop@h or \do at bptloop@h, either
+ % we've finished a complete row of point values, or we've done all
+ % the question (or page) numbers through \last at pq@index, or both:
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ % We've inserted all the point values, and there's room
+ % remaining on the current line for Total Points:
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % This is the last row; put in the total:
+ \if at bonus
+ \do at totalbpts@h
+ \else
+ \do at totalpts@h
+ \fi
\else
- \docount at pgswpts
+ % This isn't the last row. We insert (\value{num at cols} -
+ % \value{cols at done}) ampersands.
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
\fi
\fi
-}% count at pgswpts
+ % We hold off on putting in the "\\ \hline" because we may want to
+ % immediately follow it with either an "\end{tabular}" or another
+ % "\hline".
+ % Scores?
+ \if at scores
+ \\
+ \hline
+ \if at bonus
+ \@bhsword \hidden at ampersand
+ \else
+ \@hsword \hidden at ampersand
+ \fi
+ \setcounter{cols at done}{0}%
+ \do at sloop@h
+ \fi
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % This is the last line! End the tabular:
+ \\
+ \hline
+ \end{tabular}%
+ \else
+ % Don't end the tabular:
+ \\
+ \hline\hline
+ \fi
+ % Check if we should repeat:
+ \ifnum \value{current at row} < \value{num at rows}\relax
+ \let\nextdo at lines@h=\do at lines@h
+ \else
+ \let\nextdo at lines@h=\relax
+ \fi
+ \nextdo at lines@h
+}% do at lines@h
-\def\docount at pgswcpts{%
- % Called by \count at pgswpts
- % \docount at pgswcpts is used for combined gradetable.
- % Count the number of pages in range with any kind of point (bonus
- % or non-bonus):
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \addtocounter{num at cols}{1}%
+\def\do at comblines@h{%
+ % Called only by \@multirowtable.
+ % Combined tables.
+ \addtocounter{current at row}{1}% Set to the number of the current row
+ \iftbl at pgs
+ \@chpgword
\else
- \check at bnsptpage
+ \@chqword
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at docount=\docount at pgswcpts
+ \setcounter{cols at done}{0}%
+ \do at pq@indexloop at h
+ % When we finish \do at pq@indexloop at h, either we've finished a
+ % complete row of page (or question) numbers, or we've done all
+ % the page (or question) numbers through \last at pq@index, or both:
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ % We've inserted all the question (or page) numbers, and there's
+ % room remaining on the current line for \@chtword:
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % This is the last row; put in the total:
+ \do at htword@h
+ \else
+ % This isn't the last row. We insert (\value{num at cols} -
+ % \value{cols at done}) ampersands.
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
+ \fi
+ \fi
+ \\
+ \hline
+ % Point values go here!
+ \@chpword
+ \setcounter{cols at done}{0}%
+ \do at ptloop@h
+ % When we finish \do at ptloop@h, either we've finished a complete
+ % row of point values, or we've done all the question (or page)
+ % numbers through \last at pq@index, or both:
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ % We've inserted all the point values, and there's room
+ % remaining on the current line for Total Points:
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % This is the last row; put in the total:
+ \do at totalpts@h
+ \else
+ % This isn't the last row. We insert (\value{num at cols} -
+ % \value{cols at done}) ampersands.
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
+ \fi
+ \fi
+ \\
+ \hline
+ % Bonus point values go here!
+ \@chbpword
+ \setcounter{cols at done}{0}%
+ \do at bptloop@h
+ % When we finish \do at bptloop@h, either
+ % we've finished a complete row of point values, or we've done all
+ % the question (or page) numbers through \last at pq@index, or both:
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ % We've inserted all the point values, and there's room
+ % remaining on the current line for Total Points:
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % This is the last row; put in the total:
+ \do at totalbpts@h
+ \else
+ % This isn't the last row. We insert (\value{num at cols} -
+ % \value{cols at done}) ampersands.
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
+ \fi
+ \fi
+ % We hold off on putting in the "\\ \hline" because we may want to
+ % immediately follow it with either an "\end{tabular}" or another
+ % "\hline".
+ % Scores?
+ \if at scores
+ \\
+ \hline
+ \@chsword \hidden at ampersand
+ \setcounter{cols at done}{0}%
+ \do at sloop@h
+ \fi
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % This is the last line! End the tabular:
+ \\
+ \hline
+ \end{tabular}%
\else
- \let\next at docount=\relax
+ % Don't end the tabular:
+ \\
+ \hline\hline
\fi
- \next at docount
-}% docount at pgswcpts
-\def\check at bnsptpage{%
- % We don't understand why we need to hide this inside of a macro:
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \addtocounter{num at cols}{1}%
+ % Check if we should repeat:
+ \ifnum \value{current at row} < \value{num at rows}\relax
+ \let\nextdo at comblines@h=\do at comblines@h
+ \else
+ \let\nextdo at comblines@h=\relax
\fi
-}% check at bnsptpage
+ \nextdo at comblines@h
+}% do at comblines@h
-\def\docount at pgswpts{%
- % Called by \count at pgswpts
- % \docount at pgswpts is used for non-bonus gradetable:
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \addtocounter{num at cols}{1}%
+\def\do at pq@indexloop at h{%
+ % Called by both \do at lines@h and \do at comblines@h.
+ % We insert at most one row of pq at index:
+ \increment at index{pq at index}%
+ \ifnum \value{pq at index} > \last at pq@index\relax
+ % Do nothing!
+ \else
+ \hidden at ampersand
+ \refto at index{pq at index}%
+ \addtocounter{cols at done}{1}%
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at docount=\docount at pgswpts
+ \ifnum \value{pq at index} < \last at pq@index\relax
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ \let\nextdo at pq@indexloop at h=\do at pq@indexloop at h
+ \else
+ \let\nextdo at pq@indexloop at h=\relax
+ \fi
\else
- \let\next at docount=\relax
+ \let\nextdo at pq@indexloop at h=\relax
\fi
- \next at docount
-}% docount at pgswpts
+ \nextdo at pq@indexloop at h
+}% do at pq@indexloop at h
-\def\docount at pgswbpts{%
- % Called by \count at pgswpts
- % \docount at pgswbpts is used for bonusgradetable:
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \addtocounter{num at cols}{1}%
+\def\do at ptloop@h{%
+ % Called by both \do at lines@h and \do at comblines@h.
+ % We insert at most one row of non-bonus point values:
+ \increment at index{pq at index@pts}%
+ \ifnum \value{pq at index@pts} > \last at pq@index\relax
+ % Do nothing!
+ \else
+ \hidden at ampersand
+ \addtocounter{cols at done}{1}%
+ \pointsof at index{pq at index@pts}%
+ \addto at hlfcntr{tbl at points}{\pointsof at index{pq at index@pts}}%
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at docount=\docount at pgswbpts
+ \ifnum \value{pq at index@pts} < \last at pq@index\relax
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ \let\nextdo at ptloop@h=\do at ptloop@h
+ \else
+ \let\nextdo at ptloop@h=\relax
+ \fi
\else
- \let\next at docount=\relax
+ \let\nextdo at ptloop@h=\relax
\fi
- \next at docount
-}% docount at pgswbpts
+ \nextdo at ptloop@h
+}% do at ptloop@h
-%--------------------------------------------------------------------
+\def\do at bptloop@h{%
+ % Called by both \do at lines@h and \do at comblines@h.
+ % We insert at most one row of bonus point values:
+ \increment at index{pq at index@bpts}%
+ \ifnum \value{pq at index@bpts} > \last at pq@index\relax
+ % Do nothing!
+ \else
+ \hidden at ampersand
+ \addtocounter{cols at done}{1}%
+ \bonuspointsof at index{pq at index@bpts}%
+ \addto at hlfcntr{tbl at bonuspoints}{\bonuspointsof at index{pq at index@bpts}}%
+ \fi
+ \ifnum \value{pq at index@bpts} < \last at pq@index\relax
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ \let\nextdo at bptloop@h=\do at bptloop@h
+ \else
+ \let\nextdo at bptloop@h=\relax
+ \fi
+ \else
+ \let\nextdo at bptloop@h=\relax
+ \fi
+ \nextdo at bptloop@h
+}% do at bptloop@h
-\def\@htblpages{%
- % We get here from \@whchtblpgs.
- % Horizontal grade or point table, by pages:
- \begingroup
- \renewcommand\arraystretch{\@gtblstretch}%
- % Set num at cols equal to the number of pages with points (of
- % correct type):
- \count at pgswpts
- % Suppress ``extra alignment tab'' errors if \thenum at cols = 0:
- \ifnum \thenum at cols = 0\relax
- \setcounter{num at cols}{1}%
- \fi
- \set at hlfcntr{tbl at points}{0}%
- \set at hlfcntr{tbl at bonuspoints}{0}%
+\def\do at htword@h{%
+ % Called by both \do at lines@h and \do at comblines@h.
+ % We insert (\value{num at cols} - \value{cols at done}) ampersands,
+ % and then either \@htword or \@bhtword or \@chtword:
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
+ \if at combined
+ \@chtword
+ \else
\if at bonus
- % Horizontal bonus grade or point table, by pages:
- \begin{tabular}{|l|*{\thenum at cols}{c|}c|}
- \hline
- {\@bhpgword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at bpgnumloop
- {\@bhtword}\\
- \hline
- {\@bhpword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at bpgptloop
- \prt at tablebonuspoints\\
- \hline
- % If it's a grade table, do the line for scores:
- \if at scores
- {\@bhsword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at bpgsloop
- \\
- \hline
- \fi
- \end{tabular}%
+ \@bhtword
\else
- \if at combined
- % Horizontal combined grade or point table, by pages:
- \begin{tabular}{|l|*{\thenum at cols}{c|}c|}
- \hline
- {\@chpgword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at cpgnumloop
- {\@chtword}\\
- \hline
- {\@chpword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at cpgptloop
- \prt at tablepoints\\
- \hline
- {\@chbpword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at cbpgptloop
- \prt at tablebonuspoints\\
- \hline
- % If it's a grade table, do the line for scores:
- \if at scores
- {\@chsword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at cpgsloop
- \\
- \hline
- \fi
- \end{tabular}%
- \else
- % Horizontal non-bonus grade or point table, by pages:
- \begin{tabular}{|l|*{\thenum at cols}{c|}c|}
- \hline
- {\@hpgword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at pgnumloop
- {\@htword}\\
- \hline
- {\@hpword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at pgptloop
- \prt at tablepoints\\
- \hline
- % If it's a grade table, do the line for scores:
- \if at scores
- {\@hsword}& \setcounter{@iterator}{\tbl at firstp}%
- \addtocounter{@iterator}{-1}\do at pgsloop
- \\
- \hline
- \fi
- \end{tabular}%
- \fi
+ \@htword
\fi
- \endgroup
-}% @htblpages
+ \fi
+}% do at htword@h
-%--------------------------------------------------------------------
-% \do at pgnumloop, \do at pgptloop, and \do at pgsloop
-% are only for non-bonus gradetable.
-% \pg at line is also for combinedgradetable.
-\def\do at pgnumloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at line
+\def\do at totalpts@h{%
+ % Called by both \do at lines@h and \do at comblines@h.
+ % We insert (\value{num at cols} - \value{cols at done}) ampersands
+ % and then the total points:
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
+ \prt at tablepoints
+}% do at totalpts@h
+
+\def\do at totalbpts@h{%
+ % Called by both \do at lines@h and \do at comblines@h.
+ % We insert (\value{num at cols} - \value{cols at done}) ampersands,
+ % and then the total bonus points:
+ \setcounter{@iterator}{\value{num at cols}}%
+ \addtocounter{@iterator}{-\value{cols at done}}%
+ \do at emptycols@h
+ \prt at tablebonuspoints
+}% do at totalbpts@h
+
+\def\do at emptycols@h{%
+ % Called by \do at lines@h, \do at comblines@h, \do at htword@h,
+ % \do at totalpts@h, and \do at totalbpts@h.
+ % We insert \value{@iterator} ampersands:
+ \ifnum \value{@iterator} > 0\relax
+ \hidden at ampersand
+ \addtocounter{@iterator}{-1}%
+ \let\nextdo at emptycols@h=\do at emptycols@h
+ \else
+ \let\nextdo at emptycols@h=\relax
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pgnumloop=\do at pgnumloop
+ \nextdo at emptycols@h
+}% do at emptycols@h
+
+\def\do at sloop@h{%
+ % Called by both \do at lines@h and \do at comblines@h.
+ % We assume that cols at done has been set to zero.
+ % We insert num at cols \hbox to \@cellwidth,
+ % separated by ampersands.
+ \addtocounter{cols at done}{1}%
+ \hbox to \@cellwidth{\hfill}%
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ \hidden at ampersand
+ \let\nextdo at sloop@h=\do at sloop@h
\else
- \let\next at pgnumloop=\relax
+ \let\nextdo at sloop@h=\relax
\fi
- \next at pgnumloop
-}% \do at pgnumloop
-\def\pg at line{%
- % We still don't know why we need to hide this inside of a macro:
- \pageref{firstpoints at onpage@\arabic{@iterator}}&
-}% \pg at line
+ \nextdo at sloop@h
+}% do at sloop@h
-\def\do at pgptloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at points}{tmp at hlfcntr}%
- \pgpt at entry
+
+%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+% Multicolumn tables
+
+
+%--------------------------------------------------------------------
+% Here's an example of a multicolumn grade table indexed by questions,
+% to show how we're getting the \cline's to link up correctly with the
+% \vline's.
+
+% Every line of \cline's is followed by a
+% \noalign{\vskip\arrayrulewidth} to cancel the
+% \noalign{\vskip-\arrayrulewidth} that ends the definition of
+% \cline.
+
+% \begin{tabular}{*2{@{}c|c|c@{}c}}
+% \cline{1-3} \cline{5-7}
+% \noalign{\vskip\arrayrulewidth}
+% \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+% Question%
+% \hspace*{\fill}%
+% & Points%
+% & \hspace*{\fill}%
+% Score%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline
+% & \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+% & \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+% Question%
+% \hspace*{\fill}%
+% & Points%
+% & \hspace*{\fill}%
+% Score%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline\\
+% \cline{1-3} \cline{5-7}
+% \noalign{\vskip\arrayrulewidth}
+% \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+% 1\hspace*{\fill}%
+% & 5%
+% & \hspace*{\fill}%
+% \hbox to \@cellwidth{\hfill}%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline
+% & \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+% & \vline\hspace*{\tabcolsep}\hspace*{\fill}%
+% 4%
+% \hspace*{\fill}%
+% & 20%
+% & \hspace*{\fill}%
+% \hbox to \@cellwidth{\hfill}%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline\\
+% \cline{1-3} \cline{5-7}
+% \noalign{\vskip\arrayrulewidth}
+% \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+% 2%
+% \hspace*{\fill}%
+% & 10%
+% & \hspace*{\fill}%
+% \hbox to \@cellwidth{\hfill}%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline
+% & \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+% & \vline\hspace*{\tabcolsep}\hspace*{\fill}%
+% 5%
+% \hspace*{\fill}%
+% & 25%
+% & \hspace*{\fill}%
+% \hbox to \@cellwidth{\hfill}%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline\\
+% \cline{1-3} \cline{5-7}
+% \noalign{\vskip\arrayrulewidth}
+% \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+% 3%
+% \hspace*{\fill}%
+% & 15%
+% & \hspace*{\fill}%
+% \hbox to \@cellwidth{\hfill}%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline
+% & \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+% & \vline\hspace*{\tabcolsep}\hspace*{\fill}%
+% Total:%
+% \hspace*{\fill}%
+% & 75%
+% & \hspace*{\fill}%
+% \hbox to \@cellwidth{\hfill}%
+% \hspace*{\tabcolsep}\hspace*{\fill}\vline\\
+% \cline{1-3} \cline{5-7}
+% \noalign{\vskip\arrayrulewidth}
+% \end{tabular}
+%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+% Check that the number of cols is OK, and compute the number of rows:
+
+\def\check at num@cols at v{%
+ % We get here from \tbl at v@or at h.
+ % We make sure the number of cols is between 1 and 10 (since we
+ % can't handle more than 10 cols in a multicolumn table).
+ % If it is, we go on to \@computenumrows at v
+ \ifnum \value{num at cols} < 1\relax
+ \ClassError{exam}{%
+ The number of columns in a table must be positive.\MessageBreak
+ }{%
+ The number of columns must be a positive integer.\MessageBreak
+ }%
+ \fbox{\textbf{Error:} Multicolumn table with no columns!}%
+ \else
+ \ifnum \value{num at cols} > 10\relax
+ \ClassError{exam}{%
+ Multicolumn tables can have at most 10 columns.\MessageBreak
+ }{%
+ Multicolumn tables can have at most 10 columns.\MessageBreak
+ }%
+ \fbox{\textbf{Error:} Multicolumn table with more than 10 columns!}%
+ \else
+ \@computenumrows at v
+ \fi
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pgptloop=\do at pgptloop
+}% check at num@cols at v
+
+\def\@computenumrows at v{%
+ % We get here from \check at num@cols at v.
+ % Compute the number of rows.
+ % First: set num at rows to one more than the number of either
+ % (questions) or (pages with the appropriate type of points), to
+ % have slots for the total along with the questions or page numbers:
+ \iftbl at pgs
+ \count at pgswpts{num at rows}%
+ \addtocounter{num at rows}{1}%
\else
- \let\next at pgptloop=\relax
+ \setcounter{num at rows}{\last at pq@index}%
+ \addtocounter{num at rows}{-\first at pq@index}%
+ \addtocounter{num at rows}{2}%
\fi
- \next at pgptloop
-}% \do at pgptloop
-% \pgpt at entry is used by different macros:
-\def\pgpt at entry{%
- % We still don't know why we need to hide this inside of a macro:
- \pointsonpage{\the at iterator}&
-}% \pgpt at entry
+ % Save the number of slots needed, using pq at index@bpts as a scratch
+ % counter, to check for truncation on division:
+ \setcounter{pq at index@bpts}{\value{num at rows}}%
+ % Divide the number of slots needed by num at cols:
+ \divide \csname c at num@rows\endcsname by
+ \csname c at num@cols\endcsname
+ % Division truncates: See if there was truncation.
+ % Use the counter @iterator as a scratch counter:
+ \setcounter{@iterator}{\value{num at rows}}%
+ \multiply \csname c@@iterator\endcsname by
+ \csname c at num@cols\endcsname
+ \ifnum \value{@iterator} < \value{pq at index@bpts}\relax
+ % There was truncation; add one to num at rows:
+ \addtocounter{num at rows}{1}%
+ \fi
+ \@multicolumntable
+}% @computenumrows at v
-\def\do at pgsloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at sentry
+%--------------------------------------------------------------------
+% Construct the actual table:
+
+\def\@multicolumntable{%
+ % We get here from \@computenumrows at v.
+ % Set \cline at stuff@v equal to the line of \cline's:
+ \create at cline@stuff at v
+ \renewcommand\arraystretch{\@gtblstretch}%
+ \set at hlfcntr{tbl at points}{0}%
+ \set at hlfcntr{tbl at bonuspoints}{0}%
+ \if at combined
+ \if at scores
+ % combinedgradetable, possibly partial.
+ % Note: We'll never use the final "c" in the format of the
+ % tabular, but there's no harm in that.
+ \begin{tabular}{*{\value{num at cols}}{@{}c|c|c|c@{}c}}
+ % We need to make sure that the \cline at stuff@v commands come
+ % *immediately* following the \\ or \begin{tabular} (with no
+ % conditionals evaluated, even if those conditionals expand to
+ % the empty string)!
+ % Put in the row of column headings, with \cline at stuff@v above and
+ % below:
+ \cline at stuff@v
+ \setcounter{@iterator}{0}%
+ \docolumn at heads@comb at v
+ \\
+ \cline at stuff@v
+ \else
+ % combinedpointtable, possibly partial.
+ % Note: We'll never use the final "c" in the format of the
+ % tabular, but there's no harm in that.
+ \begin{tabular}{*{\value{num at cols}}{@{}c|c|c@{}c}}
+ % We need to make sure that the \cline at stuff@v commands come
+ % *immediately* following the \\ or \begin{tabular} (with no
+ % conditionals evaluated, even if those conditionals expand to
+ % the empty string)!
+ % Put in the row of column headings, with \cline at stuff@v above and
+ % below:
+ \cline at stuff@v
+ \setcounter{@iterator}{0}%
+ \docolumn at heads@comb at noscores@v
+ \\
+ \cline at stuff@v
+ \fi
+ % pq at index@pts will hold the question number (or page number) in
+ % the first column of the row.
+ \setcounter{pq at index@pts}{\first at pq@index}%
+ \iftbl at pgs
+ % If we're indexed by pages, we need to make sure there are
+ % points of the appropriate type on the first page listed:
+ \addtocounter{pq at index@pts}{-1}%
+ \find at nextpagewithpoints{pq at index@pts}%
+ \fi
+ \setcounter{current at row}{0}%
+ \do at lines@v
+ \else
+ % It's not combined:
+ \if at scores
+ % Note: We'll never use the final "c" in the format of the
+ % tabular, but there's no harm in that.
+ \begin{tabular}{*{\value{num at cols}}{@{}c|c|c@{}c}}
+ % We need to make sure that the \cline at stuff@v commands come
+ % *immediately* following the \\ or \begin{tabular} (with no
+ % conditionals evaluated, even if those conditionals expand to
+ % the empty string)!
+ % Put in the row of column headings, with \cline at stuff@v above and
+ % below:
+ \cline at stuff@v
+ \setcounter{@iterator}{0}%
+ \docolumn at heads@v
+ \\
+ \cline at stuff@v
+ \else
+ % Note: We'll never use the final "c" in the format of the
+ % tabular, but there's no harm in that.
+ \begin{tabular}{*{\value{num at cols}}{@{}c|c@{}c}}
+ % We need to make sure that the \cline at stuff@v commands come
+ % *immediately* following the \\ or \begin{tabular} (with no
+ % conditionals evaluated, even if those conditionals expand to
+ % the empty string)!
+ % Put in the row of column headings, with \cline at stuff@v above and
+ % below:
+ \cline at stuff@v
+ \setcounter{@iterator}{0}%
+ \docolumn at heads@noscores at v
+ \\
+ \cline at stuff@v
+ \fi
+ % pq at index@pts will hold the question number (or page number) in
+ % the first column of the row.
+ \setcounter{pq at index@pts}{\first at pq@index}%
+ \iftbl at pgs
+ % If we're indexed by pages, we need to make sure there are
+ % points of the appropriate type on the first page listed:
+ \addtocounter{pq at index@pts}{-1}%
+ \find at nextpagewithpoints{pq at index@pts}%
+ \fi
+ \setcounter{current at row}{0}%
+ \do at lines@v
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at pgsloop=\do at pgsloop
+}% @multicolumntable
+
+%--------------------------------------------------------------------
+% \create at cline@stuff at v
+
+% The function \create at cline@stuff at v defines \cline at stuff@v to be whatever's
+% appropriate given the values of num at cols, \if at bonus, \if at combined, and
+% \if at scores.
+
+% We wimped out of generating \cline at stuff@v on the fly because we didn't
+% see how to get the correct expansions/nonexpansions without using a
+% primitive of e-TeX.
+
+% \clines at ii@whatever is for tables in which a logical column consists
+% of two columns; it's used for pointtable and bonuspointtable.
+
+\def\clines at ii@i{\cline{1-2}}
+\def\clines at ii@ii{\cline{1-2} \cline{4-5}}
+\def\clines at ii@iii{\cline{1-2} \cline{4-5} \cline{7-8}}
+\def\clines at ii@iv{\cline{1-2} \cline{4-5} \cline{7-8} \cline{10-11}}
+\def\clines at ii@v{\cline{1-2} \cline{4-5} \cline{7-8} \cline{10-11}
+ \cline{13-14}}
+\def\clines at ii@vi{\cline{1-2} \cline{4-5} \cline{7-8} \cline{10-11}
+ \cline{13-14} \cline{16-17}}
+\def\clines at ii@vii{\cline{1-2} \cline{4-5} \cline{7-8} \cline{10-11}
+ \cline{13-14} \cline{16-17} \cline{19-20}}
+\def\clines at ii@viii{\cline{1-2} \cline{4-5} \cline{7-8} \cline{10-11}
+ \cline{13-14} \cline{16-17} \cline{19-20} \cline{22-23}}
+\def\clines at ii@vix{\cline{1-2} \cline{4-5} \cline{7-8} \cline{10-11}
+ \cline{13-14} \cline{16-17} \cline{19-20} \cline{22-23}
+ \cline{25-26}}
+\def\clines at ii@x{\cline{1-2} \cline{4-5} \cline{7-8} \cline{10-11}
+ \cline{13-14} \cline{16-17} \cline{19-20} \cline{22-23}
+ \cline{25-26} \cline{28-29}}
+
+% \clines at iii@whatever is for tables in which a logical column consists
+% of three columns; it's are used for gradetable, bonusgradetable, and
+% combinedpointtable:
+
+\def\clines at iii@i{\cline{1-3}}
+\def\clines at iii@ii{\cline{1-3} \cline{5-7}}
+\def\clines at iii@iii{\cline{1-3} \cline{5-7} \cline{9-11}}
+\def\clines at iii@iv{\cline{1-3} \cline{5-7} \cline{9-11} \cline{13-15}}
+\def\clines at iii@v{\cline{1-3} \cline{5-7} \cline{9-11} \cline{13-15}
+ \cline{17-19}}
+\def\clines at iii@vi{\cline{1-3} \cline{5-7} \cline{9-11} \cline{13-15}
+ \cline{17-19} \cline{21-23}}
+\def\clines at iii@vii{\cline{1-3} \cline{5-7} \cline{9-11} \cline{13-15}
+ \cline{17-19} \cline{21-23} \cline{25-27}}
+\def\clines at iii@viii{\cline{1-3} \cline{5-7} \cline{9-11} \cline{13-15}
+ \cline{17-19} \cline{21-23} \cline{25-27} \cline{29-31}}
+\def\clines at iii@ix{\cline{1-3} \cline{5-7} \cline{9-11} \cline{13-15}
+ \cline{17-19} \cline{21-23} \cline{25-27} \cline{29-31}
+ \cline{33-35}}
+\def\clines at iii@x{\cline{1-3} \cline{5-7} \cline{9-11} \cline{13-15}
+ \cline{17-19} \cline{21-23} \cline{25-27} \cline{29-31}
+ \cline{33-35} \cline{37-39}}
+
+
+% \clines at iv@whatever is for tables in which a logical column
+% consists of four columns; it's used for combinedgradetable.
+
+\def\clines at iv@i{\cline{1-4}}
+\def\clines at iv@ii{\cline{1-4} \cline{6-9}}
+\def\clines at iv@iii{\cline{1-4} \cline{6-9} \cline{11-14}}
+\def\clines at iv@iv{\cline{1-4} \cline{6-9} \cline{11-14} \cline{16-19}}
+\def\clines at iv@v{\cline{1-4} \cline{6-9} \cline{11-14} \cline{16-19}
+ \cline{21-24}}
+\def\clines at iv@vi{\cline{1-4} \cline{6-9} \cline{11-14} \cline{16-19}
+ \cline{21-24} \cline{26-29}}
+\def\clines at iv@vii{\cline{1-4} \cline{6-9} \cline{11-14} \cline{16-19}
+ \cline{21-24} \cline{26-29} \cline{31-34}}
+\def\clines at iv@viii{\cline{1-4} \cline{6-9} \cline{11-14} \cline{16-19}
+ \cline{21-24} \cline{26-29} \cline{31-34} \cline{36-39}}
+\def\clines at iv@ix{\cline{1-4} \cline{6-9} \cline{11-14} \cline{16-19}
+ \cline{21-24} \cline{26-29} \cline{31-34} \cline{36-39}
+ \cline{41-44}}
+\def\clines at iv@x{\cline{1-4} \cline{6-9} \cline{11-14} \cline{16-19}
+ \cline{21-24} \cline{26-29} \cline{31-34} \cline{36-39}
+ \cline{41-44} \cline{46-49}}
+
+% The definition of \cline ends with \noalign{\vskip-\arrayrulewidth},
+% and so we want to throw in a \noalign{\vskip\arrayrulewidth} to
+% cancel that.
+\def\cline at correction{\noalign{\vskip\arrayrulewidth}}
+
+\def\create at cline@stuff at v{%
+ % Called by \@multicolumntable.
+ \if at combined
+ \if at scores
+ \edef\cline at stuff@v{\expandafter\noexpand\csname
+ clines at iv@\romannumeral \c at num@cols\endcsname
+ \noexpand\cline at correction}%
+ \else
+ \edef\cline at stuff@v{\expandafter\noexpand\csname
+ clines at iii@\romannumeral \c at num@cols\endcsname
+ \noexpand\cline at correction}%
+ \fi
\else
- \let\next at pgsloop=\relax
+ \if at scores
+ \edef\cline at stuff@v{\expandafter\noexpand\csname
+ clines at iii@\romannumeral \c at num@cols\endcsname
+ \noexpand\cline at correction}%
+ \else
+ \edef\cline at stuff@v{\expandafter\noexpand\csname
+ clines at ii@\romannumeral \c at num@cols\endcsname
+ \noexpand\cline at correction}%
+ \fi
\fi
- \next at pgsloop
-}% \do at pgsloop
-% \pg at sentry is called by several different macros,
-% to create different tables:
-\def\pg at sentry{%
- % We still don't know why we need to hide this inside of a macro:
- \hbox to \@cellwidth{\hfill}&
-}% \pg at sentry
+}% create at cline@stuff at v
%--------------------------------------------------------------------
-% These things are for bonusgradetable:
+% The various \docolumn at heads@something at v
-% \do at bpgnumloop, \do at bpgptloop, \do at bpgsloop,
-% and \bpg at sline are only for bonusgradetable.
-% \bpg at line is also used for combinedgradetable.
-\def\do at bpgnumloop{%
+\def\docolumn at heads@v{%
+ % Called by \@multicolumntable.
+ % multicolumngradetable or multicolumnbonusgradetable, possibly
+ % partial.
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \iftbl at pgs
+ \if at bonus
+ \@bvpgword
+ \else
+ \@vpgword
+ \fi
+ \else
+ \if at bonus
+ \@bvqword
+ \else
+ \@vqword
+ \fi
+ \fi
+ \hspace*{\fill}%
+ & \if at bonus
+ \@bvpword
+ \else
+ \@vpword
+ \fi
+ & \hspace*{\fill}%
+ \if at bonus
+ \@bvsword
+ \else
+ \@vsword
+ \fi
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
\addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \bpg at line
+ \ifnum \value{@iterator} < \value{num at cols}\relax
+ \hidden at ampersand
+ \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+ \hidden at ampersand
+ \let\nextdocolumn at heads@v=\docolumn at heads@v
+ \else
+ \let\nextdocolumn at heads@v=\relax
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at bpgnumloop=\do at bpgnumloop
+ \nextdocolumn at heads@v
+}% docolumn at heads@v
+
+\def\docolumn at heads@noscores at v{%
+ % Called by \@multicolumntable.
+ % multicolumnpointtable or multicolumnbonuspointtable, possibly
+ % partial.
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \iftbl at pgs
+ \if at bonus
+ \@bvpgword
+ \else
+ \@vpgword
+ \fi
+ \else
+ \if at bonus
+ \@bvqword
+ \else
+ \@vqword
+ \fi
+ \fi
+ \hspace*{\fill}%
+ & \hspace*{\fill}%
+ \if at bonus
+ \@bvpword
+ \else
+ \@vpword
+ \fi
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \addtocounter{@iterator}{1}%
+ \ifnum \value{@iterator} < \value{num at cols}\relax
+ \hidden at ampersand
+ \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+ \hidden at ampersand
+ \let\nextdocolumn at heads@noscores at v=\docolumn at heads@noscores at v
\else
- \let\next at bpgnumloop=\relax
+ \let\nextdocolumn at heads@noscores at v=\relax
\fi
- \next at bpgnumloop
-}% do at bpgnumloop
-\def\bpg at line{%
- % We still don't know why we need to hide this inside of a macro:
- \pageref{firstbonuspoints at onpage@\arabic{@iterator}}&
-}% bpg at line
+ \nextdocolumn at heads@noscores at v
+}% docolumn at heads@noscores at v
-\def\do at bpgptloop{%
+\def\docolumn at heads@comb at v{%
+ % Called by \@multicolumntable.
+ % multicolumncombinedgradetable, possibly partial.
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \iftbl at pgs
+ \@cvpgword
+ \else
+ \@cvqword
+ \fi
+ \hspace*{\fill}%
+ & \@cvpword
+ & \@cvbpword
+ & \hspace*{\fill}%
+ \@cvsword
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
\addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at bonuspoints}{tmp at hlfcntr}%
- \bpgpt at line
- \fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at bpgptloop=\do at bpgptloop
+ \ifnum \value{@iterator} < \value{num at cols}\relax
+ \hidden at ampersand
+ \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+ \hidden at ampersand
+ \let\nextdocolumn at heads@comb at v=\docolumn at heads@comb at v
\else
- \let\next at bpgptloop=\relax
+ \let\nextdocolumn at heads@comb at v=\relax
\fi
- \next at bpgptloop
-}% do at bpgptloop
-% \bpgpt at line is called by several macros:
-\def\bpgpt at line{%
- % We still don't know why we need to hide this inside of a macro:
- \bonuspointsonpage{\the at iterator}&
-}% bpgpt at line
+ \nextdocolumn at heads@comb at v
+}% docolumn at heads@comb at v
-\def\do at bpgsloop{%
+\def\docolumn at heads@comb at noscores@v{%
+ % Called by \@multicolumntable.
+ % multicolumncombinedpointtable, possibly partial.
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \iftbl at pgs
+ \@cvpgword
+ \else
+ \@cvqword
+ \fi
+ \hspace*{\fill}%
+ & \@vpword
+ & \hspace*{\fill}%
+ \@bvpword
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
\addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at sentry
- \fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at bpgsloop=\do at bpgsloop
+ \ifnum \value{@iterator} < \value{num at cols}\relax
+ \hidden at ampersand
+ \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+ \hidden at ampersand
+ \let\nextdocolumn at heads@comb at noscores@v=\docolumn at heads@comb at noscores@v
\else
- \let\next at bpgsloop=\relax
+ \let\nextdocolumn at heads@comb at noscores@v=\relax
\fi
- \next at bpgsloop
-}% do at bpgsloop
+ \nextdocolumn at heads@comb at noscores@v
+}% docolumn at heads@comb at noscores@v
%--------------------------------------------------------------------
-% These things are for combinedgradetable:
+% \do at lines@v is used by *all* multicolumn tables.
+% It calls \do at oneline@v for all non-combined tables and
+% \do at oneline@comb at v for all combined tables.
-% \do at cpgnumloop, \cpg at line, \cbpg at line, \do at cpgptloop, \bpgpt at line,
-% \do at cpgsloop, \bpg at sline, and \do at cbpgptloop are only for
-% combinedgradetable:
-\def\do at cpgnumloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at line
+\def\do at lines@v{%
+ % We get here from \@multicolumntable.
+ % ALL MULTICOLUMN TABLES!!!!
+ % pq at index@pts holds the question number or page number in the first
+ % column of the current row.
+ \addtocounter{current at row}{1}%
+ \setcounter{pq at index}{\value{pq at index@pts}}%
+ \setcounter{cols at done}{0}% Number of columns done
+ % We're doing both grade tables and point tables!!
+ \if at combined
+ \do at oneline@comb at v
\else
- \check at bpgpts
+ \do at oneline@v
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at cpgnumloop=\do at cpgnumloop
+ \increment at index{pq at index@pts}%
+ % We need the "\\ \cline at stuff@v" to *immediately* precede the
+ % \end{tabular} (i.e., with no \ifnum separating them), to avoid
+ % having crap after the \cline at stuff@v that
+ % causes there to be an extra row at the end of the table. We also
+ % need there to be nothing between \\ and \cline at stuff@v.
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ \\
+ \cline at stuff@v
+ \end{tabular}%
+ \let\nextdo at lines@v=\relax
\else
- \let\next at cpgnumloop=\relax
+ \\
+ \cline at stuff@v
+ \let\nextdo at lines@v=\do at lines@v
\fi
- \next at cpgnumloop
-}% do at bpgnumloop
-\def\check at bpgpts{%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \bpg at line
- \fi
-}% check at bpgpts
+ \nextdo at lines@v
+}% do at lines@v
-\def\do at cpgptloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at points}{tmp at hlfcntr}%
- \pgpt at entry
+\def\do at oneline@v{%
+ % Called by \do at lines@v.
+ % Used for all multicolumn non-combined tables.
+ % pq at index holds the question or page number we're about to do.
+ \ifnum \value{pq at index} > \last at pq@index\relax
+ % See if we're in the last column; use pq at index@bpts as a scratch
+ % counter:
+ \setcounter{pq at index@bpts}{\value{cols at done}}%
+ \addtocounter{pq at index@bpts}{1}%
+ \ifnum \value{pq at index@bpts} = \value{num at cols}\relax
+ % We're in the last column; are we in the last row?
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % We're in the last column, last row!
+ % Print the total:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \if at bonus
+ \@bvtword
+ \else
+ \@vtword
+ \fi
+ \hspace*{\fill}%
+ \hidden at ampersand
+ \if at scores
+ \if at bonus
+ \prt at tablebonuspoints
+ \else
+ \prt at tablepoints
+ \fi
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \else
+ \hspace*{\fill}%
+ \if at bonus
+ \prt at tablebonuspoints
+ \else
+ \prt at tablepoints
+ \fi
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
+ \else
+ % Not last column last row; insert empty space:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\fill}%
+ \if at scores
+ \hidden at ampersand
+ \hbox to \@cellwidth{\hfill}%
+ \fi
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
+ \else
+ % Not last column; insert empty space:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\fill}%
+ \if at scores
+ \hidden at ampersand
+ \hbox to \@cellwidth{\hfill}%
+ \fi
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
\else
- \check at cbpts
+ % We need to do question (or page) number pq at index:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \refto at index{pq at index}%
+ \hspace*{\fill}%
+ \hidden at ampersand
+ \if at scores
+ \if at bonus
+ \bonuspointsof at index{pq at index}%
+ \addto at hlfcntr{tbl at bonuspoints}{\bonuspointsof at index{pq at index}}%
+ \else
+ \pointsof at index{pq at index}%
+ \addto at hlfcntr{tbl at points}{\pointsof at index{pq at index}}%
+ \fi
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \else
+ \hspace*{\fill}%
+ \if at bonus
+ \bonuspointsof at index{pq at index}%
+ \addto at hlfcntr{tbl at bonuspoints}{\bonuspointsof at index{pq at index}}%
+ \else
+ \pointsof at index{pq at index}%
+ \addto at hlfcntr{tbl at points}{\pointsof at index{pq at index}}%
+ \fi
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at cpgptloop=\do at cpgptloop
+ \addtocounter{cols at done}{1}% Number of columns done
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ \hidden at ampersand
+ \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+ \nextcolumn at index@v{pq at index}%
+ \hidden at ampersand
+ \let\nextdo at oneline@v=\do at oneline@v
\else
- \let\next at cpgptloop=\relax
+ \let\nextdo at oneline@v=\relax
\fi
- \next at cpgptloop
-}% do at cpgptloop
-\def\check at cbpts{%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pgpt at entry
- \fi
-}% check at cbpts
+ \nextdo at oneline@v
+}% do at oneline@v
-\def\do at cbpgptloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \add at hlfcntrtohlfcntr{tbl at bonuspoints}{tmp at hlfcntr}%
- \bpgpt at line
+\def\do at oneline@comb at v{%
+ % Called by \do at lines@v.
+ % All combined multicolumn tables.
+ % pq at index holds the question (or page) we're about to do.
+ \ifnum \value{pq at index} > \last at pq@index\relax
+ % See if we're in the last column; use pq at index@bpts as a scratch
+ % counter:
+ \setcounter{pq at index@bpts}{\value{cols at done}}%
+ \addtocounter{pq at index@bpts}{1}%
+ \ifnum \value{pq at index@bpts} = \value{num at cols}\relax
+ % We're in the last column; are we in the last row?
+ \ifnum \value{current at row} = \value{num at rows}\relax
+ % We're in the last column, last row!
+ % Print the total:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \@cvtword
+ \hspace*{\fill}%
+ \hidden at ampersand
+ \prt at tablepoints
+ \hidden at ampersand
+ \if at scores
+ \prt at tablebonuspoints
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \else
+ \hspace*{\fill}%
+ \prt at tablebonuspoints
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
+ \else
+ % Last column, but not last row; insert empty space:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\fill}%
+ \hidden at ampersand
+ \hbox to \@cellwidth{\hfill}%
+ \if at scores
+ \hidden at ampersand
+ \hbox to \@cellwidth{\hfill}%
+ \fi
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
+ \else
+ % Not last column; insert empty space:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\fill}%
+ \hidden at ampersand
+ \hbox to \@cellwidth{\hfill}%
+ \if at scores
+ \hidden at ampersand
+ \hbox to \@cellwidth{\hfill}%
+ \fi
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
\else
- \check at cnonpts
+ % We need to do question number pq at index:
+ \vline \hspace*{\tabcolsep}\hspace*{\fill}%
+ \refto at index{pq at index}%
+ \hspace*{\fill}%
+ \hidden at ampersand
+ \pointsof at index{pq at index}%
+ \addto at hlfcntr{tbl at points}{\pointsof at index{pq at index}}%
+ \hidden at ampersand
+ \if at scores
+ \bonuspointsof at index{pq at index}%
+ \addto at hlfcntr{tbl at bonuspoints}{\bonuspointsof at index{pq at index}}%
+ \hidden at ampersand
+ \hspace*{\fill}%
+ \hbox to \@cellwidth{\hfill}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \else
+ \hspace*{\fill}%
+ \bonuspointsof at index{pq at index}%
+ \addto at hlfcntr{tbl at bonuspoints}{\bonuspointsof at index{pq at index}}%
+ \hspace*{\tabcolsep}\hspace*{\fill}\vline
+ \fi
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at cbpgptloop=\do at cbpgptloop
+ \addtocounter{cols at done}{1}% Number of columns done
+ \ifnum \value{cols at done} < \value{num at cols}\relax
+ \hidden at ampersand
+ \hspace*{-\arrayrulewidth}\hspace*{\doublerulesep}%
+ \nextcolumn at index@v{pq at index}%
+ \hidden at ampersand
+ \let\nextdo at oneline@comb at v=\do at oneline@comb at v
\else
- \let\next at cbpgptloop=\relax
+ \let\nextdo at oneline@comb at v=\relax
\fi
- \next at cbpgptloop
-}% do at cbpgptloop
-\def\check at cnonpts{%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \bpgpt at line
+ \nextdo at oneline@comb at v
+}% do at oneline@comb at v
+
+%--------------------------------------------------------------------
+% \find at nextpagewithpoints and \find at nextcolumnpage@v:
+
+\def\find at nextpagewithpoints#1{%
+ % Called by \dofind at nextcolumnpage@v, \increment at index, and
+ % \@multicolumntable.
+ % The argument #1 should be the name of a counter with a nonnegative
+ % value.
+ % We increase #1 by at least 1 to either the number of the
+ % next page containing the appropriate kind of points, or to something
+ % greater than \tbl at lastp.
+ \addtocounter{#1}{1}%
+ \if at combined
+ \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\value{#1}}}%
+ \addto at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\value{#1}}}%
+ % The sum is positive when at least one of them is positive.
+ \else
+ \if at bonus
+ \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\value{#1}}}%
+ \else
+ \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\value{#1}}}%
+ \fi
\fi
-}% check at cnonpts
-
-\def\do at cpgsloop{%
- \addtocounter{@iterator}{1}%
- \set at hlfcntr{tmp at hlfcntr}{\pointsonpage{\the at iterator}}%
\ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at sentry
+ \let\nextfind at nextpagewithpoints=\relax
\else
- \check at bnsline
+ \ifnum \value{#1} > \tbl at lastp\relax
+ \let\nextfind at nextpagewithpoints=\relax
+ \else
+ \def\nextfind at nextpagewithpoints{\find at nextpagewithpoints{#1}}%
+ \fi
\fi
- \ifnum \the at iterator < \tbl at lastp\relax
- \let\next at cpgsloop=\do at cpgsloop
+ \nextfind at nextpagewithpoints
+}% find at nextpagewithpoints
+
+\def\find at nextcolumnpage@v#1{%
+ % Called by \nextcolumn at index@v.
+ % This is used for all multicolumn tables that are indexed by
+ % pages.
+ % We use \find at nextpagewithpoints to increment #1 to either
+ % the (num at rows)'th page number after #1 that contains the
+ % appropriate kind of points or to a value greater than \tbl at lastp.
+ % We use pq at index@bpts as a scratch counter.
+ \setcounter{pq at index@bpts}{0}%
+ \dofind at nextcolumnpage@v{#1}%
+}% find at nextcolumnpage@v
+\def\dofind at nextcolumnpage@v#1{%
+ % Called only by \find at nextcolumnpage@v.
+ \addtocounter{pq at index@bpts}{1}%
+ \find at nextpagewithpoints{#1}%
+ \ifnum \value{pq at index@bpts} = \value{num at rows}\relax
+ \let\nextdofind at nextcolumnpage@v=\relax
\else
- \let\next at cpgsloop=\relax
+ % The following test shouldn't be needed, in theory, because the
+ % computation of num at cols should prevent trouble, but we're being
+ % paranoid.
+ \ifnum \value{#1} > \tbl at lastp\relax
+ \let\nextdofind at nextcolumnpage@v=\relax
+ \else
+ % Note: this is a \def, and not a \let, because we need to put
+ % in the argument #1:
+ \def\nextdofind at nextcolumnpage@v{\dofind at nextcolumnpage@v{#1}}%
+ \fi
\fi
- \next at cpgsloop
-}% do at cpgsloop
-\def\check at bnsline{%
- \set at hlfcntr{tmp at hlfcntr}{\bonuspointsonpage{\the at iterator}}%
- \ifhlfcntr at pos{tmp at hlfcntr}%
- \pg at sentry
- \fi
-}% check at bnsline
+ \nextdofind at nextcolumnpage@v
+}% dofind at nextcolumnpage@v
%--------------------------------------------------------------------
-% \pointsinrange and \bonuspointsinrange:
+% \pointsinrange and \bonuspointsinrange, and then
+% \firstqinrange, \lastqinrange, and \numqinrange.
+
+
% We say either \@bonusfalse or \@bonustrue, and then we check it only
% in \do at countloop:
\def\pointsinrange#1{%
@@ -6203,7 +7460,7 @@
\@bonusfalse
\def\tbl at range{#1}%
\@ifundefined{exam at numpoints}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
{\read at range}%
}% pointsinrange
@@ -6211,19 +7468,22 @@
\@bonustrue
\def\tbl at range{#1}%
\@ifundefined{exam at numpoints}%
- {\mbox{\normalfont\bf ??}}%
+ {\mbox{\normalfont\bfseries ??}}%
{\read at range}%
}% bonuspointsinrange
\def\bad at range{%
- {\mbox{\normalfont\bf ??}}%
+ % Called by \read at range, \firstqinrange, \lastqinrange, and
+ % \numqinrange.
+ {\mbox{\normalfont\bfseries ??}}%
\ClassWarning{exam}{%
- Grading range `\tbl at range ' not defined.\MessageBreak
+ Grading range `\tbl at range' not defined.\MessageBreak
\space\space Run LaTeX again.\MessageBreak
}%
}% bad at range
\def\read at range{%
+ % Called by \pointsinrange and \bonuspointsinrange.
\@ifundefined{range@\tbl at range @firstq}%
{%
\bad at range
@@ -6238,7 +7498,7 @@
\edef\tbl at lastq{\csname range@\tbl at range @lastq\endcsname}%
% Check that firstq precedes or equals lastq:
\ifnum \tbl at firstq > \tbl at lastq\relax
- \fbox{Error: Grading Range `\tbl at range ':
+ \fbox{\textbf{Error:} Grading Range `\tbl at range ':
Last question precedes first question.}%
\ClassError{exam}{%
In grading range `\tbl at range ',
@@ -6289,26 +7549,29 @@
% \firstqinrange, \lastqinrange, and \numqinrange.
\newcommand{\firstqinrange}[1]{%
- \@ifundefined{range@#1 at firstq}%
- {\mbox{\normalfont\bf ??}}%
+ \def\tbl at range{#1}%
+ \@ifundefined{range@\tbl at range @firstq}%
+ {\bad at range}%
{\csname range@#1 at firstq\endcsname}%
}% firstqinrange
\newcommand{\lastqinrange}[1]{%
- \@ifundefined{range@#1 at lastq}%
- {\mbox{\normalfont\bf ??}}%
+ \def\tbl at range{#1}%
+ \@ifundefined{range@\tbl at range @lastq}%
+ {\bad at range}%
{\csname range@#1 at lastq\endcsname}%
}% lastqinrange
\newcommand{\numqinrange}[1]{%
+ \def\tbl at range{#1}%
\@ifundefined{range@#1 at firstq}%
{%
- \mbox{\normalfont\bf ??}%
+ \bad at range
}%
{%
\@ifundefined{range@#1 at lastq}%
{%
- \mbox{\normalfont\bf ??}%
+ \bad at range
}%
{%
\setcounter{@iterator}{\csname range@#1 at lastq\endcsname}%
@@ -6319,6 +7582,7 @@
}%
}% numqinrange
+
%--------------------------------------------------------------------
%--------------------------------------------------------------------
%
@@ -6632,12 +7896,63 @@
% much vertical space, then it will spill out of the bottom of the
% box, overwriting whatever follows the box.
+% 2016/02/08: The solutionbox frame can now be printed in color, as
+% long as you load color.sty in the preamble.
+%
+% Usage: Say
+%
+% \usepackage{color}
+%
+% in the preamble, and then give the command
+%
+% \colorsolutionboxes
+%
+% to have the frame around a solutionbox in color. The default color
+% was created by the command
+%
+% \definecolor{SolutionBoxColor}{gray}{0.8}
+%
+% and you can change the color by giving a new \definecolor command
+% (which must be done *after* the \colorsolutionboxes command).
+%
+% To cancel color solutionbox frames and return to black, give the
+% command
+%
+% \nocolorsolutionboxes
+
+\newif\if at colorsolutionboxes
+\@colorsolutionboxesfalse
+\def\colorsolutionboxes{%
+ \@ifundefined{definecolor}
+ {%
+ \ClassError{exam}{%
+ You must load the color package with the command\MessageBreak
+ \space\space\protect\usepackage{color}\MessageBreak
+ in order to use the command \protect\colorsolutionboxes
+ \MessageBreak
+ }{%
+ This command makes use of the package color.sty,\MessageBreak
+ and so you have to load color.sty before your\MessageBreak
+ \protect\begin{document} command.\MessageBreak
+ }%
+ }%
+ {%
+ \definecolor{SolutionBoxColor}{gray}{0.8}
+ \@colorsolutionboxestrue
+ }%
+}
+\def\nocolorsolutionboxes{\@colorsolutionboxesfalse}
+
\newbox\exam at box
\newenvironment{solutionbox}[1]{%
\@insolutiontrue % cancelled by the end of the environment
\@addpointsfalse % cancelled by the end of the environment
\def\solutionbox at size{#1}% saved for end of environment
- \@tempdima=\textwidth
+% Change, 2016/02/08: So that the solutionbox environment will work
+% correctly inside of a tabular environment, we use \hsize instead of
+% \textwidth:
+% \@tempdima=\textwidth
+ \@tempdima=\hsize
\advance\@tempdima -\@totalleftmargin
\advance\@tempdima -6\fboxsep
\advance\@tempdima -2\fboxrule
@@ -6654,6 +7969,11 @@
\leftskip=0pt
\rightskip=0pt
\vskip 2\fboxsep
+% Change, 2016/05/09: We change \@totalleftmargin and \linewidth in
+% case there are enumerate, itemize, or description environments
+% inside the solution:
+ \@totalleftmargin=0pt
+ \linewidth=\hsize
\solutiontitle
\ignorespaces
}%
@@ -6673,7 +7993,8 @@
% \parshape) shift us to the right when we enter horizontal
% mode. If we don't use this \hbox, then we'd have to comment
% out the \hskip \@totalleftmargin:
- \hbox to \textwidth{%
+ % 2016/02/08: Changed \textwidth to \hsize:
+ \hbox to \hsize{%
\noindent
\hskip\@totalleftmargin
\hskip3\fboxsep\hskip\fboxrule
@@ -6682,15 +8003,41 @@
\par\nointerlineskip
\fi
\endgroup % Finish confining the \Solution at Emphasis
- \makeemptybox{\solutionbox at size}%
- }
+% Starting in version 2.502, 2016/03/23,the decision of whether to
+% color the box is made in the \makeemptybox command:
+ \makeemptybox{\solutionbox at size}
+ }% End of the second argument of \newenvironment{solutionbox}
+%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+% Added in version 2.502: 2016/03/23, \colorfbox
+% The \colorfbox command is used in our modification of framed.sty
+% that allows us to print the frame around the solution in color when
+% the user has given the command \colorsolutionboxes. It takes two
+% arguments, the first being the color for the frame, and the second
+% being the stuff to be framed.
+% If we had assumed that color.sty was used (instead of just color.sty),
+% then the line that saves the current color in saved at color could have
+% been just
+% \colorlet{saved at color}{.}
+% but we wanted to make this work even if color.sty is being used.
+% When you define a color mycolor using either color.sty or
+% xcolor.sty, a macro \csname\string\color@ mycolor\endcsname is
+% defined (i.e., the macro name is \\color at mycolor).
+\newcommand{\colorfbox}[2]{%
+ % Save the current color in saved at color:
+ \expandafter\let\csname\string\color at saved@color\endcsname\current at color
+ % Create the box in color #1, with the text in saved at color
+ % (the braces are to confine the color change commands):
+ {\color{#1}\fbox{\color{saved at color}#2}}%
+}% colorfbox
+
%--------------------------------------------------------------------
%--------------------------------------------------------------------
@@ -6945,7 +8292,19 @@
\catcode`\|=\FrameRestore
% Provide configuration commands:
-\providecommand\FrameCommand{\fboxrule=\FrameRule \fboxsep=\FrameSep \fbox}
+%psh: Version 2.502, 2016/03/23, changed \FrameCommand so that the
+% frame is printed in color if the user has said
+% \colorsolutionboxes:
+%\providecommand\FrameCommand{\fboxrule=\FrameRule \fboxsep=\FrameSep \fbox}
+\def\FrameCommand{\fboxrule=\FrameRule \fboxsep=\FrameSep
+ \if at colorsolutionboxes
+ \def\box at it{\colorfbox{SolutionBoxColor}}%
+ \else
+ \def\box at it{\fbox}%
+ \fi
+ \box at it
+}% \FrameCommand
+
\@ifundefined{FrameRule}{\newdimen\FrameRule \FrameRule=\fboxrule}{}
\@ifundefined{FrameSep} {\newdimen\FrameSep \FrameSep =3\fboxsep}{}
More information about the tex-live-commits
mailing list