Newer
Older
LaTeX / coursehandbook.cls
\def\coursehandbookdate{6 December 2024}
\def\coursehandbookversion{1.0.3}
\def\coursehandbookshortdate{2024/12/06}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Document class for course handbooks.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Version History
% v1.0   Initial version.
% v1.0.1 Added siunitx to required packages.
% v1.0.2 Modified header generation to translate short teaching period strings
%        into long equivalents (e.g., "S1" => "Semester One").
% v1.0.3 Replaced deprecated ifpdf and ifxetex with iftex.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\NeedsTeXFormat{LaTeX2e}[2001/06/01]
\ProvidesClass{coursehandbook}%
         [\coursehandbookshortdate\space v\coursehandbookversion\space INFO course handbook style]

\RequirePackage{iftex}
\RequirePackage{kvoptions}	% Key-value option handling.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Option processing.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\SetupKeyvalOptions{family=handbook, prefix=handbook@}

\DeclareBoolOption{showanswers}
\DeclareComplementaryOption{hideanswers}{showanswers}

\DeclareStringOption[INFO]{subjectcode}
\DeclareStringOption[!!PAPER NUMBER UNDEFINED!!]{papernumber}
\DeclareStringOption[!!PAPER TITLE UNDEFINED!!]{papertitle}
\DeclareStringOption[!!PAPER YEAR UNDEFINED!!]{paperyear}
\DeclareStringOption[!!PAPER PERIOD UNDEFINED!!]{paperperiod}
\DeclareStringOption[!!AUTHORS UNDEFINED!!]{authors}

% \DeclareBoolOption{pdftex}
% \DeclareBoolOption{xetex}
% 
% \ifxetex
% 	\DeclareVoidOption{xetex}
% 	\OptionNotUsed{pdftex}
% \else\ifpdf
% 	\DeclareBoolOption{pdftex}
% 	\OptionNotUsed{xetex}
% \else
% 	\ClassError{coursehandbook}{The coursehandbook document class only\MessageBreak\ supports PDF(La)TeX and XeTeX.}{The coursehandbook document class only supoprts the pdftex and\MessageBreak\ xetex drivers. Please use one of these.}
% \fi

\DeclareDefaultOption{%
	\ifx\CurrentOptionValue\relax%
		\expandafter\PassOptionsToClass%
		\expandafter{\CurrentOption}{book}%
	\else%
		\@unknownoptionerror%
	\fi%
}

\ProcessKeyvalOptions*
\LoadClass{book}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% A bunch o' packages.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ifxetex
	\RequirePackage{fontspec}	% Font handling for XeTeX.
	\RequirePackage{xunicode}
	\RequirePackage{xltxtra}
\else
	% Note that fontenc freaks out if any of the keyval option values
	% are surrounded by braces (?!). Spaces get eaten without braces,
	% so instead use \ in \documentclass to preserve them.
	\RequirePackage[T1]{fontenc}
	\RequirePackage{textcomp}
\fi
\RequirePackage{mathpazo}	    % Palatino for text and maths.
\RequirePackage{graphicx}		% Include graphics of all sorts.
\RequirePackage{color}			% Color handling.
\RequirePackage[hmargin=68.393315pt,% Sensible margins, essentially the same as a4wide.
                top=107.1438pt,%
                bottom=116.90304pt]{geometry}
% \RequirePackage{makeidx}
\RequirePackage{amssymb}		% AMS maths symbols.
\RequirePackage{latexsym}		% Extra LaTeX maths symbols.
\RequirePackage{relalg}			% Relational algebra symbols.
% \RequirePackage{longtable}	% For multi-page tables.
\RequirePackage{multirow}		% Multi-row cells in tables.
\RequirePackage{rotating}		% Rotate stuff.
\RequirePackage{fancyhdr}		% Fancy page headers & footers.
\RequirePackage{verbatim}		% Enhanced verbatim handling.
\RequirePackage{listings}		% Nicely formatted code listings.
\RequirePackage[normalem]{ulem}	% Fancy underlining, strike-through, etc.
\usepackage[detect-all,binary-units]{siunitx}	% SI unit and number formatting.
% \RequirePackage{moreverb}
% \RequirePackage{listings}		% Pretty-print code listings; not currently used.

\RequirePackage{count1to}		% Needed to get the absolute page numbers.
\RequirePackage{calc}			% Needed to calculate page numbers for 2-up version.
\RequirePackage{parskip}        % Space-separated rather than indented paragraphs.

\RequirePackage[%
	plainpages=false,   % Stops pdfTeX complaining about duplicate page numbers.
	colorlinks=true,%
	urlcolor=blue,		% Acceptable for print or screen
	linkcolor=blue,		% Acceptable for print or screen
	bookmarks=true,%
	bookmarksopen=true,%
	bookmarksnumbered=true,%
	pdfpagemode=UseOutlines,%
	pdfstartview=FitB,%
]{hyperref}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Various setup macros to enable on-the-fly option changing.
% These are particularly necessary for paper detail options (such as
% papertitle) that may contain spaces. From the kvoptions documentation:
%
% ==================================================
%	* Spaces are removed, regardless where:
%		\documentclass[box=0 0 400 600]{article}
%	  Now each package will see box=00400600 as global option.
%
%	* In the previous case also braces would not help:
%		\documentclass[box={0 0 400 600}]{article}
%	  The result is an error message:
%		! LaTeX Error: Missing \begin{document}.
%
%	* The requirements on robustness are extremly high. LATEX expands the
%	  option. All that will not work as environment name will break also
%	  as option. Even a \relax will generate an error message:
%		! Missing \endcsname inserted.
%	  Of course, LATEX does not use its protecting mechanisms. On contrary
%	  \protect itself will cause errors.
% ==================================================
%
% The upshot is that in the \documentclass, spaces are eaten, but we can't use
% {} or macros like \space or "\ " to escape them. The only thing that does
% work is:
%
%	papertitle=some\csname space\endcsname name
%
% which is particularly ugly. A better solution is to follow the hyperref
% model and have a "setup" macro that sets these options AFTER the
% \documentclass.
%
% These also call \hypersetup to ensure that the PDF metadata match.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Set arbitrary class options.
\newcommand{\handbooksetup}[1]{%
	\setkeys{handbook}{#1}%
	\@updatepdfmetadata%
}

% \papersetup is intended to be for setting paper detail options, but is
% essentially just a synonym of \handbooksetup.
\let\papersetup\handbooksetup

% Macros for setting specific paper detail options.
\newcommand{\setsubjectcode}[1]{%
	\@setpaperoption{subjectcode}{#1}%
}
\newcommand{\setpapernumber}[1]{%
	\@setpaperoption{papernumber}{#1}%
}
\newcommand{\setpapertitle}[1]{%
	\@setpaperoption{papertitle}{#1}%
}
\newcommand{\setpaperyear}[1]{%
	\expandafter\@setpaperoption{paperyear}{#1}%
}
\newcommand{\setpaperperiod}[1]{%
	\@setpaperoption{paperperiod}{#1}%
}
\newcommand{\setauthors}[1]{%
	\@setpaperoption{authors}{#1}%
}

\newcommand{\@setpaperoption}[2]{%
	\setkeys{handbook}{#1={#2}}
	\@updatepdfmetadata%
}

\def\@updatepdfmetadata{%
	\hypersetup{%
		pdftitle={\expandafter\handbook@subjectcode\ \expandafter\handbook@papernumber\ Handbook, \expandafter\handbook@paperyear},%
		pdfauthor={\expandafter\handbook@authors},%
		pdfsubject={Student Handbook for \expandafter\handbook@subjectcode\ \expandafter\handbook@papernumber, \expandafter\handbook@paperyear.}%
	}%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Set up fonts.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ifxetex
	\defaultfontfeatures{Mapping=tex-text}
	\setmainfont{TeX Gyre Pagella}
	\setmonofont[Scale=MatchLowercase]{Letter Gothic 12 Pitch}
	% Not sure about these?
	\setsansfont[Scale=MatchLowercase]{Futura Book}
	\newfontfamily\headerfont[Size=11]{Futura Light}
\else
	\renewcommand{\sfdefault}{bfu}
	\renewcommand{\ttdefault}{blg}
	\DeclareFixedFont{\headerfont}{T1}{bfu}{lc}{n}{11}
\fi


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Set up listings.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Pre-load the most obviously used languages. You can still use other languages,
% just not as quickly.
\lstloadlanguages{Oracle,Java}

% Set defaults.
\lstset{basicstyle=\ttfamily,basewidth=0.5em,escapeinside={(@}{@)},
	showspaces=false,showstringspaces=false}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Miscellaneous stuff.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Useful macros for paper code, etc.
\def\PaperCode{\expandafter\handbook@subjectcode\ \expandafter\handbook@papernumber}
\def\ShortPaperCode{\expandafter\handbook@subjectcode\expandafter\handbook@papernumber}
\def\PaperTitle{\expandafter\handbook@papertitle}
\def\PaperYear{\expandafter\handbook@paperyear}
\def\PaperPeriod{\expandafter\handbook@paperperiod}
\def\HandbookAuthors{\expandafter\handbook@authors}

% Stolen from ouexam :).
\def\@SONE{S1}
\def\@STWO{S2}
\def\@SS{SS}
\def\@FY{FY}
\newcommand{\PaperLongPeriod}{%
  \ifx\handbook@paperperiod\@SONE Semester One%
  \else\ifx\handbook@paperperiod\@STWO Semester Two%
  \else\ifx\handbook@paperperiod\@SS Summer School%
  \else\ifx\handbook@paperperiod\@FY Full Year%
  \else\PaperPeriod%
  \fi\fi\fi\fi%
}

% Handbook name.
\newcommand{\handbookname}{Student Handbook}

% "Chapter" names. Note that the lab and tutorial names are dependent on
% the setting of the showanswers class option.
\newcommand{\introchaptername}{Introductory Chapter}
\newcommand{\labname}{\ifhandbook@showanswers Selected Answers for \fi\PaperCode\ Lab}
\newcommand{\tutorialname}{\ifhandbook@showanswers Selected Answers for \fi\PaperCode\ Tutorial}

% listings.sty has problems with in-line verbatim code and fancy styles
% (backgrounds, borders), hence this:
\newcommand{\code}[1]{\texttt{#1}}

% Other useful macros.
\newcommand{\term}[1]{\textit{#1}}
\newcommand{\foreign}[1]{\textit{#1}}
\newcommand{\BookTitle}[1]{\textit{#1}}

% Backslashes - what a pain!
\newcommand{\bs}{\(\backslash{}\)}

% We want "chapter" numbers to reset for each part.
\@addtoreset{chapter}{part}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Set up fancy headings.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Although we don't actually use the "fancy" page style, we have to set it
% initially in order for the page marks to be set up correctly.
\pagestyle{fancy}
\fancyhf{}

% Page marks. \partmark is completely new, the others are standard.
\newcommand{\partmark}[1]{\markboth{\partname\ \thepart---#1}{}}
\renewcommand{\chaptermark}[1]{\markright{\@chapapp\ \thechapter---#1}}
\renewcommand{\sectionmark}[1]{}

\setlength{\headheight}{15pt}

% No running head or foot rules.
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}

% Use | to separate items in the header/footer.
\newcommand{\LeftHeadingBullet}{\(\vert\)}
\newcommand{\RightHeadingBullet}{\(\vert\)}
\newlength{\HeadingBulletSpacing}
\setlength{\HeadingBulletSpacing}{0.5em}

% The headers and footers are set up as follows, where "TOC" = table of
% contents, "1st" = first page of part or chapter, "part" = title page of
% a part, "plain" = plain page style, "empty" = empty page style,
% "#" = page number, "LO" = left odd, "RE" = right even, etc. If something
% isn't mentioned, it's empty.
%
% Note that we're optimising for 2-up printing, so the placement of page
% numbers on even/odd pages is the opposite of what you'd normally expect.
% TODO: make this a switchable option?
%
% Headers:
% 	{plain,TOC} LO		# | <subjectcode> <papernumber> STUDENT HANDBOOK
% 	{plain,TOC} RO		<paperperiod>, <paperyear>
% 	TOC LE				<empty>
% 	TOC RE				CONTENTS | #
% 	plain LE			PART <partnumber>---<parttitle>
% 	plain RE			<sectiontype> <sectionnumber>---<sectiontitle> | #
% 	{empty,1st,part} *	<empty>
%
% Footers:
% 	{plain,TOC,empty,part} *	<empty>
% 	1st LO					# |
%	1st RE					| #
%
% For ease of definition, here are some macros:
\def\@plainHeadLO{\headerfont{\thepage{}\hspace{\HeadingBulletSpacing}\LeftHeadingBullet\hspace{\HeadingBulletSpacing}\MakeUppercase{\PaperCode\ \handbookname}}}
\def\@plainHeadRO{\headerfont{\MakeUppercase{\PaperLongPeriod, \PaperYear}}}
\def\@plainHeadLE{\headerfont{\MakeUppercase{\leftmark}}}
\def\@plainHeadRE{\headerfont{\MakeUppercase{\rightmark}\hspace{\HeadingBulletSpacing}\RightHeadingBullet\hspace{\HeadingBulletSpacing}\thepage}}
\def\@tocHeadLE{}
\def\@tocHeadRE{\headerfont{\MakeUppercase{\contentsname}\hspace{\HeadingBulletSpacing}\RightHeadingBullet\hspace{\HeadingBulletSpacing}\thepage}}
\def\@firstFootLO{\headerfont{\thepage\hspace{\HeadingBulletSpacing}\LeftHeadingBullet}}
\def\@firstFootRO{\headerfont{\LeftHeadingBullet\hspace{\HeadingBulletSpacing}\thepage}}

% Plain style is automatically set when we use \chapter or \part, but
% this becomes a bit complicated, because we want a different appearance
% for the first page of a chapter (simple footer only) vs. the title page of
% a part (no header or footer at all). The simplest solution seems to be to
% define a \newif that tells us if we're in part mode (default false) and sets
% up the style accordingly. We then just have to overload the original
% \chapter and \part macros to set the flag appropriately (see below).
\newif\if@inpart \@inpartfalse

\fancypagestyle{plain}{%
	\fancyhf{}%
	\if@inpart\else%
		\fancyfoot[LO]{\headerfont{\thepage\hspace{\HeadingBulletSpacing}\LeftHeadingBullet}}%
		\fancyfoot[RE]{\headerfont{\LeftHeadingBullet\hspace{\HeadingBulletSpacing}\thepage}}%
	\fi%
}

% Heading style for table of contents.
\fancypagestyle{toc}{%
	\fancyhf{}%
	\fancyhead[LO]{\@plainHeadLO}%
	\fancyhead[RO]{\@plainHeadRO}%
	\fancyhead[LE]{\@tocHeadLE}%
	\fancyhead[RE]{\@tocHeadRE}%
}

% "normal" is the new "plain" :)
% We use this rather than just \pagestyle{fancy}, because we need to
% explicitly switch styles in a couple of places (e.g., TOC). It would
% probably have made more sense to just redefine the "fancy" style, but
% that seems to make LaTeX grind to a halt.
\fancypagestyle{normal}{%
	\fancyhf{}%
	\fancyhead[LO]{\@plainHeadLO}%
	\fancyhead[RO]{\@plainHeadRO}%
	\fancyhead[LE]{\@plainHeadLE}%
	\fancyhead[RE]{\@plainHeadRE}%
}

\pagestyle{normal}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Create title page.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\maketitlepage}{%
	% TODO:
	%  - Add University logo?
	\thispagestyle{empty}%
	\vspace*{\stretch{1}}%
	\begin{flushright}%
		\Huge\PaperCode \\%
		\PaperTitle \\%
		\rule{\textwidth}{3pt} \\[0.25\baselineskip]%
		\huge \handbookname \\[1.1\baselineskip]%
		\Large\HandbookAuthors%
	\end{flushright}%
	\vspace*{\stretch{2}}%
	\begin{center}%
		\scshape\Large Department of Information Science \\%
		University of Otago \\[0.25\baselineskip]%
		\PaperYear%
	\end{center}%
	\vspace*{\stretch{0.3}}%
	\clearpage\thispagestyle{empty}% blank, empty page
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Table of contents.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Add a wrapper around the book class's \tableofcontents macro so we can
% easily change the page style for the TOC section (and more importantly,
% change it back). This also lets us hook in our own tracking of various
% things like chapter titles.
\let\@booktableofcontents\tableofcontents
\renewcommand\tableofcontents{%
	\pagestyle{toc}%
	\@booktableofcontents%
	\clearpage\thispagestyle{toc}%
    \pagestyle{normal}%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Different modes for different parts of the document. The behaviour here
% is analogous to the \appendix macro.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% This macro updates relevant internal parameters in hyperref so that
% correct PDF bookmarks are generated.
\newcommand\@hyperrefsetup[1]{%
	\def\Hy@chapapp{#1}%
	\renewcommand{\theHchapter}{\theHpart.\arabic{chapter}}%
	\renewcommand{\theHsection}{\theHpart.\theHchapter.\arabic{section}}%
	\renewcommand{\theHsubsection}{\theHpart.\theHchapter.\theHsection.\arabic{subsection}}%
	\renewcommand{\theHsubsubsection}{\theHpart.\theHchapter.\theHsection.\theHsubsection.\arabic{subsubsection}}%
}

% Introduction part.
\newcommand\intro{%
	\gdef\@chapapp{\introchaptername}%
	\@hyperrefsetup{introchapter}%
}

% Labs part.
\newcommand\labs{%
	\gdef\@chapapp{\labname}%
	\@hyperrefsetup{lab}%
}

% Tutorials part.
\newcommand\tutorials{%
	\gdef\@chapapp{\tutorialname}%
	\@hyperrefsetup{tutorial}%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Sectioning.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Wrappers for \chapter for each of labs, tutorials and "ordinary" chapters.
% These all make the chapter title available through \CurrentChapterTitle.
%
% TODO: I wanted to override \chapter and refactor \general to \chapter, but
% the TOC seems to wig out when I try it. Probably not that crucial...
%\let\@bookchapter\chapter
%
% \renewcommand{\chapter}[1]%
% {%
% 	\@bookchapter{#1}%
% 	\renewcommand{\CurrentChapterTitle}{#1}%
% }
%
% TODO: prehaps rename \general to \introchapter?
\newcommand{\general}[1]{\@inpartfalse\chapter{#1}}

\newcommand{\lab}[1]{\@inpartfalse\chapter{#1}}

\newcommand{\tutorial}[1]{\@inpartfalse\chapter{#1}}

\newcommand{\handbookpart}[1]{\@inparttrue\part{#1}\partmark{#1}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Answers handling.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ifhandbook@showanswers
	\newenvironment{answer}{\par\vspace{0.5em}\itshape}{\normalfont\vspace{0.5em}}
\else
	\newenvironment{answer}{%
		\@bsphack%
		\let\do\@makeother\dospecials\catcode`\^^M\active%
		\let\verbatim@startline\relax%
		\let\verbatim@addtoline\@gobble%
		\let\verbatim@processline\relax%
		\let\verbatim@finish\relax%
		\verbatim@%
	}{\@esphack}
\fi


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Set up auxiliary file so that we can write out the first and last
% absolute page number for each tutorial and lab exercise. We can then use
% this to automatically generate a separate PDF for each exercise.
%
\newcounter{absolutepage}
\newcounter{absolutepagetwoup}

\newcommand{\markfirstpage}[1]{%
	\setcounter{absolutepage}{\the\count1}%
	\stepcounter{absolutepage}%
	\immediate\write\@auxout{\string\@writefile{bmk}{\string#1.1up.first=\theabsolutepage}}%
	\setcounter{absolutepagetwoup}{\value{absolutepage}/2+1}%
	\immediate\write\@auxout{\string\@writefile{bmk}{\string#1.2up.first=\theabsolutepagetwoup}}%
}

\newcommand{\marklastpage}[1]{%
	\cleardoublepage% can't just add 1 because we may be skipping 2 pages
	\immediate\write\@auxout{\string\@writefile{bmk}{\string#1.1up.last=\the\count1}}%
	\setcounter{absolutepagetwoup}{\the\count1/2}%
	\immediate\write\@auxout{\string\@writefile{bmk}{\string#1.2up.last=\theabsolutepagetwoup}}%
}


\endinput