texlive[49727] Master: exframe (16jan19)

commits+karl at tug.org commits+karl at tug.org
Wed Jan 16 23:21:34 CET 2019


Revision: 49727
          http://tug.org/svn/texlive?view=revision&revision=49727
Author:   karl
Date:     2019-01-16 23:21:34 +0100 (Wed, 16 Jan 2019)
Log Message:
-----------
exframe (16jan19)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/exframe/
    trunk/Master/texmf-dist/doc/latex/exframe/README.txt
    trunk/Master/texmf-dist/doc/latex/exframe/exframe.pdf
    trunk/Master/texmf-dist/doc/latex/exframe/exfsmp1.tex
    trunk/Master/texmf-dist/source/latex/exframe/
    trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx
    trunk/Master/texmf-dist/source/latex/exframe/exframe.ins
    trunk/Master/texmf-dist/tex/latex/exframe/
    trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty
    trunk/Master/tlpkg/tlpsrc/exframe.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex/exframe/README.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/README.txt	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/exframe/README.txt	2019-01-16 22:21:34 UTC (rev 49727)
@@ -0,0 +1,38 @@
+exframe v3.0
+Copyright 2011-2019 Niklas Beisert
+
+exframe is a LaTeX2e package which provides a general purpose
+framework to describe and typeset exercises and exam questions
+along with their solutions. The package features mechanisms to
+hide or postpone solutions, to assign and handle points, to
+collect problems on exercise sheets, to store and use metadata
+and to implement a consistent numbering. It also provides a
+very flexible interface for configuring and customising the
+formatting, layout and representation of the exercise content.
+
+The package consists of the files
+
+    README.txt   readme file
+    exframe.ins  installation file
+    exframe.dtx  source file
+    exframe.sty  package file
+    exfsmp1.tex  sample latex file
+    exframe.pdf  manual
+
+The distribution consists of the files
+README.txt, exframe.ins and exframe.dtx.
+
+Run "(pdf)latex exframe.dtx" to compile the manual exframe.pdf.
+
+Run "latex exframe.ins" to create the package exframe.sty
+and the sample exfsmp1.tex.
+Copy the file exframe.sty to an appropriate directory of your LaTeX
+distribution, e.g. texmf-root/tex/latex/exframe.
+
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in
+  http://www.latex-project.org/lppl.txt
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.


Property changes on: trunk/Master/texmf-dist/doc/latex/exframe/README.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/exframe/exframe.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/exframe/exframe.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exframe.pdf	2019-01-16 18:58:39 UTC (rev 49726)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exframe.pdf	2019-01-16 22:21:34 UTC (rev 49727)

Property changes on: trunk/Master/texmf-dist/doc/latex/exframe/exframe.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/exframe/exfsmp1.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfsmp1.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfsmp1.tex	2019-01-16 22:21:34 UTC (rev 49727)
@@ -0,0 +1,211 @@
+%%
+%% This is file `exfsmp1.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% exframe.dtx  (with options: `sample1')
+%% 
+%% Copyright (C) 2011-2019 Niklas Beisert
+%% 
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%%   http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%% 
+\NeedsTeXFormat{LaTeX2e}[1996/12/01]
+\ProvidesFile{exfsmp1.tex}[2019/01/16 v3.0 sample 1 for exframe]
+\documentclass[12pt]{article}
+
+\usepackage{geometry}
+\geometry{layout=a4paper}
+\geometry{paper=a4paper}
+\geometry{margin=2.5cm}
+\parindent0pt
+\parskip0.5ex
+
+\usepackage{amsmath}
+\usepackage{hyperref}
+\usepackage[extstyle]{exframe}
+
+\exercisesetup{solutions=true}
+%%\exercisesetup{solutions=false}
+
+\exercisestyle{plainheader}
+\exerciseconfig{composeheaderbelowright}{\getsheetdata{points}}%
+
+\exerciseconfig{countersheet}{\Roman{sheet}}
+\exerciseconfig{countersubproblem}{\roman{subproblem})}
+\exerciseconfig{countersubproblemmax}{vii)}
+
+\exerciseconfig{termsheet}{\"Ubungsblatt}
+\exerciseconfig{termsheets}{\"Ubungsbl\"atter}
+
+\exercisestyle{pointsat=margin}
+\reversemarginpar
+\exerciseconfig{composepointsmargin}[1]{#1p.}
+
+\exerciseconfig{styletitle}{\sffamily\bfseries}
+
+\exerciseconfig{skipproblembelow}{1.5cm}
+
+\exercisestyle{fracpoints}
+\exercisestyle{solutionbelow=problem}
+\exercisestyle{solutionsep}
+
+\exerciseconfig{composemetasheet}[2]{\getexercisedata{course},
+  \exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
+
+\exercisesetup{pdfdata=sheet}
+\exercisedata{title=%
+  {\getexercisedata{course}, \getexercisedata{material}}}
+\exercisedata{author=%
+  {\getexercisedata{instructor}, \getexercisedata{institution}}}
+
+\exercisedata{institution={Katharinen-Volksschule}}
+\exercisedata{course={Mathematik}}
+\exercisedata{instructor={J.\ G.\ B\"uttner}}
+\exercisedata{period={ca.\ 1786}}
+\exercisedata{material={\"Ubungsaufgaben}}
+
+\begin{document}
+
+\begin{sheet}[number=5]
+
+\begin{problem}[title={Sums}]
+
+This problem deals with sums and series.
+
+\begin{subproblem}[points=2,difficulty=simple,label={\problemtag-simplesum}]
+Compute the sum
+\showpoints
+\begin{equation}
+1+2+3.
+\end{equation}
+
+\begin{solution}
+The result is
+\begin{equation}
+1+2+3=6.
+\end{equation}
+\end{solution}
+
+\end{subproblem}
+
+\begin{subproblem}[points=97,difficulty=lengthy]
+Compute the sum
+\begin{equation}
+1+2+3+\ldots+98+99+100.
+\end{equation}
+Keep calm and calculate!
+%%That ought to keep him occupied for a while
+\end{subproblem}
+
+\begin{solution}[author={C.\ F.\ Gau\ss}]
+We use the result $1+2+3=6$ from part \ref{\problemtag-simplesum}
+to jumpstart the calculation. The remaining sums yield
+\awardpoints[1 for each remaining sum]{97}
+\begin{equation}
+6+4+5+\ldots+99+100=5050.
+\end{equation}
+Alternatively the summands can be grouped into pairs as follows:
+\begin{align}
+1+100&=101,\\
+2+99&=101,\\
+3+98&=101,\\
+\ldots &\nonumber\\
+50+51&=101.
+\end{align}
+These amount to 50 times the same number 101.
+Therefore the sum equals
+\begin{equation}
+1+2+\ldots+99+100=50\cdot 101=5050.
+\end{equation}
+\textit{Ligget se!} \awardpoints*{97}
+\end{solution}
+
+You may give the final part a try:
+
+\begin{subproblem}[optional={optional}, difficulty={requires inspiration}]
+Compute the series
+\begin{equation}
+1+2+3+\ldots
+\end{equation}
+
+\begin{solution}
+The series is divergent, so the result is $\infty$ \awardpoints*{1}.
+\par
+However, after subtracting the divergent part,
+the result clearly is
+\begin{equation}
+\zeta(-1)=-\frac{1}{12}\,,
+\end{equation}
+where the zeta-function $\zeta(s)$ is defined by
+\begin{equation}
+\zeta(s):=\sum_{k=1}^\infty \frac{1}{k^s}\,.
+\end{equation}
+This definition holds only for $s>1$ where the sum is convergent,
+but one can continue the complex analytic function to $s<0$
+\awardpoints*{1.5}.
+\par
+Another way of understanding the result
+is to use the indefinite summation formula
+for arbitrary exponent $s$ in the summand
+(which also follows from the Euler--MacLaurin formula)
+\begin{equation}
+\sum_n n^s
+= \frac{n^{s+1}}{s+1}
+ -\sum_{j=0}^s  \frac{\zeta(j-s)\,s!}{(s-j)!\,j!}\,n^j
+= \ldots - \zeta(-s)\,n^0.
+\end{equation}
+Curiously, the constant term with $j=0$ is just the desired result
+but with the wrong sign
+(in fact, the constant term of an indefinite sum is ambiguous;
+for the claim we merely set $j=0$
+in the expression which holds for others values of $j$)
+\awardpoints*{0.5}.
+In order to understand the sign,
+we propose that the above formula describes the regularised result
+for the sum with limits $+\infty$ and $n$
+\begin{equation}
+\sum_{k=+\infty}^n k^s
+\simeq \frac{n^{s+1}}{s+1}
+ -\sum_{j=0}^s  \frac{\zeta(j-s)\,s!}{(s-j)!\,j!}\,n^j.
+\end{equation}
+Then we flip the summation limits of the desired sum
+to bring it into the above form
+\awardpoints*{0.5}
+\begin{equation}
+\sum_{k=1}^\infty k^s
+= -\sum_{k=\infty}^0 k^s
+\simeq \zeta(-s).
+\end{equation}
+\end{solution}
+
+\end{subproblem}
+
+\end{problem}
+
+\begin{problem}[points=1, difficulty=insane]
+Show that the equation
+\begin{equation}
+a^3+b^3=c^3
+\end{equation}
+has no positive integer solutions.
+\end{problem}
+
+\begin{solution}
+\normalmarginpar
+This is beyond the scope of this example.
+\marginpar{\footnotesize\raggedright does not fit here.\par}
+\end{solution}
+
+\end{sheet}
+
+\end{document}
+\endinput
+%%
+%% End of file `exfsmp1.tex'.


Property changes on: trunk/Master/texmf-dist/doc/latex/exframe/exfsmp1.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx	2019-01-16 22:21:34 UTC (rev 49727)
@@ -0,0 +1,4494 @@
+% \iffalse
+%
+% exframe.dtx Copyright (C) 2011-2019 Niklas Beisert
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+%   http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Niklas Beisert.
+%
+% This work consists of the files exframe.dtx and exframe.ins
+% and the derived files exframe.sty and exfsmp1.tex.
+%
+%<package|sample1>\NeedsTeXFormat{LaTeX2e}[1996/12/01]
+%<package>\ProvidesPackage{exframe}[2019/01/16 v3.0 Framework for Exercise Problems]
+%<sample1>\ProvidesFile{exfsmp1.tex}[2019/01/16 v3.0 sample 1 for exframe]
+%<*driver>
+\def\thedate#1{2019/01/16}\def\theversion#1{v3.0}
+\ProvidesFile{exframe.dtx}[\thedate{} \theversion{} exframe reference manual file]
+\PassOptionsToClass{10pt,a4paper}{article}
+\documentclass{ltxdoc}
+
+\usepackage[margin=35mm]{geometry}
+\usepackage{hyperref}
+\usepackage{hyperxmp}
+\usepackage[usenames]{color}
+
+\hypersetup{colorlinks=true}
+\hypersetup{pdfstartview=FitH}
+\hypersetup{pdfpagemode=UseNone}
+\hypersetup{pdfsource={}}
+\hypersetup{pdflang={en-UK}}
+\hypersetup{pdfcopyright={Copyright 2010-2019 Niklas Beisert.
+  This work may be distributed and/or modified under the
+  conditions of the LaTeX Project Public License, either version 1.3
+  of this license or (at your option) any later version.}}
+\hypersetup{pdflicenseurl={http://www.latex-project.org/lppl.txt}}
+\hypersetup{pdfcontactaddress={ETH Zurich, ITP, HIT K,
+  Wolfgang-Pauli-Strasse 27}}
+\hypersetup{pdfcontactpostcode={8093}}
+\hypersetup{pdfcontactcity={Zurich}}
+\hypersetup{pdfcontactcountry={Switzerland}}
+\hypersetup{pdfcontactemail={nbeisert at itp.phys.ethz.ch}}
+\hypersetup{pdfcontacturl={http://people.phys.ethz.ch/\xmptilde nbeisert/}}
+
+\newcommand{\secref}[1]{\hyperref[#1]{section \ref*{#1}}}
+
+\parskip1ex
+\parindent0pt
+\let\olditemize\itemize
+\def\itemize{\olditemize\parskip0pt}
+
+\begin{document}
+
+\title{The \textsf{exframe} Package}
+\hypersetup{pdftitle={The exframe Package}}
+\author{Niklas Beisert\\[2ex]
+  Institut f\"ur Theoretische Physik\\
+  Eidgen\"ossische Technische Hochschule Z\"urich\\
+  Wolfgang-Pauli-Strasse 27, 8093 Z\"urich, Switzerland\\[1ex]
+  \href{mailto:nbeisert at itp.phys.ethz.ch}
+  {\texttt{nbeisert at itp.phys.ethz.ch}}}
+\hypersetup{pdfauthor={Niklas Beisert}}
+\hypersetup{pdfsubject={Manual for the LaTeX2e Package exframe}}
+\date{\thedate{}, \theversion{}}
+\maketitle
+
+\begin{abstract}\noindent
+\textsf{exframe} is a \LaTeXe{} package
+which provides a general purpose framework to describe and typeset
+exercises and exam questions along with their solutions.
+The package features mechanisms
+to hide or postpone solutions,
+to assign and handle points,
+to collect problems on exercise sheets,
+to store and use metadata
+and to implement a consistent numbering.
+It also provides a very flexible interface for configuring and customising
+the formatting, layout and representation of the exercise content.
+\end{abstract}
+
+\begingroup
+\parskip0ex
+\tableofcontents
+\endgroup
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Introduction}
+
+This package provides a framework to describe and typeset
+exercises (homework problems, classroom exercises, quizzes, exam questions,
+exercise questions in books and lecture notes, \ldots)
+and their solutions or answers.
+The aim of this package is to set up a few \LaTeX{} environments
+into which questions and corresponding answers can be filled conveniently.
+The main task of the package is to manage the text and data
+that are provided in the source document,
+perform some common operations on them,
+and then output the content appropriately.
+The package has the following goals, tasks and features:
+%
+\begin{itemize}
+\item
+The package is designed with generality in mind.
+It is meant to be usable in many different situations.
+The primary target is science and education, but it may well
+be useful in other areas.
+
+\item
+The package defines a basic functional layout for the output
+and provides many options to reshape the layout and formatting
+according to the author's needs and wishes.
+
+\item
+The package can handle two layers of exercises:
+main problems and subproblems.
+The use of subproblems is optional.
+
+\item
+The display of solutions can be configured:
+Solutions can be hidden for a hand-out version of exercise sheets.
+When displayed, they may appear immediately,
+collectively after the problem,
+at the end of each sheet or at some manually defined location.
+
+\item
+The package can handle exercise sheets which combine several exercise problems:
+A \LaTeX{} document can consist of an individual sheet
+or of a collection of sheets (e.g.\ spanning a lecture course).
+In the latter case, the document files can be set up
+such that single sheets as well as a collection of all sheets
+can be compiled; the package \textsf{childdoc} may be of assistance.
+
+\item
+The package can handle points to be credited:
+Points will be displayed according to the layout.
+Overall points for a problem or a sheet can be added automatically.
+Points can also be stored and used elsewhere.
+
+\item
+The package provides an interface to specify exercise metadata
+(author, source, \ldots):
+Some basic types of metadata are predefined and more specific metadata
+categories can be added.
+
+\item
+The package can use alternative counters for equations
+within solutions (and problems). This is to ensure a consistent
+numbering independently of whether solutions are output or not.
+\end{itemize}
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Usage}
+\label{sec:usage}
+
+To use the package \textsf{exframe} add the command
+%
+\begin{center}
+|\usepackage{exframe}|
+\end{center}
+%
+to the preamble of the \LaTeX{} document.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Exercise Environments}
+\label{sec:environments}
+
+The package provides four environments
+to describe the main entities of exercise problems.
+Additional information on the exercises can be provided
+in the optional arguments to these environments
+which will be discussed in the following sections.
+Furthermore, a limited set of commands
+is provided for control and extra features,
+see the sections below for details.
+
+\DescribeEnv{problem}
+The |problem| environment describes
+an exercise problem:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{problem}[|\textit{opts}|]|\\
+|  |\textit{problem text and subproblems}\\
+|\end{problem}|
+\end{tabular}
+\end{center}
+%
+As one of the many available options \textit{opts},
+one can provide a title for the exercise by
+specifying |title={|\textit{title}|}|.
+If no title is given, the problem number will be displayed instead.
+See \secref{sec:metadata} and \secref{sec:points}
+for a description of the available options.
+
+\DescribeEnv{subproblem}
+The |subproblem| environment describes
+a subproblem, part or an individual question of an exercise problem:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{subproblem}[|\textit{opts}|]|\\
+|  |\textit{subproblem text}\\
+|\end{subproblem}|
+\end{tabular}
+\end{center}
+%
+A |subproblem| block must be contained within a |problem| block
+(however, a |problem| block need not contain |subproblem| blocks).
+
+\DescribeEnv{solution}
+The |solution| environment describes
+the solution to a problem or a subproblem:
+\begin{center}
+\begin{tabular}{l}
+|\begin{solution}[|\textit{opts}|]|\\
+|  |\textit{solution text}\\
+|\end{solution}|
+\end{tabular}
+\end{center}
+%
+A |solution| block should be at the end of a |subproblem| or |problem| block
+(it is not mandatory to provide a |solution|).
+It can be contained within the corresponding block or it can follow it.
+Depending on the choice of solution display, see \secref{sec:solutions},
+the output may have a slightly different layout.
+In terms of logic, it is preferred
+to define a solution \emph{within} the corresponding block;
+this may also have some technical advantages and produce
+a slightly better result in terms of layout.
+
+\DescribeEnv{sheet}
+The |sheet| environment describes an exercise sheet:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{sheet}[|\textit{opts}|]|\\
+|  |\textit{sheet text and problems}\\
+|\end{sheet}|
+\end{tabular}
+\end{center}
+%
+A sheet typically contains one or several problems
+(it is not mandatory to group problems into a |sheet|).
+There may or may not be additional auxiliary text introducing the problems.
+A header will be added to the sheet according to the specified layout.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Solution Display}
+\label{sec:solutions}
+
+There are several options to control the output of solutions.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutions}
+Most importantly, the display of solutions
+can be disabled or enabled altogether:
+%
+\begin{center}
+|\exercisesetup{solutions|[|=true|\textbar|false|]|}|
+\end{center}
+%
+Solutions are hidden by default,
+and their display needs to be activated explicitly
+(it suffices to specify the option |solutions| without the value |true|).
+It is also possible to control the display
+by an analogous package option |solutions|,
+see \secref{sec:options} for further information.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\ifsolutions}
+The display of solutions is reflected by the conditional |\ifsolutions|.
+As the hiding of solutions is performed automatically,
+the conditional would typically be used to change some details,
+e.g.\ for adjusting titles:
+%
+\begin{center}
+|\ifsolutions Solutions\||else Exercises\||fi|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutionequation}
+As solutions can contain numbered equations
+while the display of solutions can be switched on and off,
+it is important to assign a different counter for equations within solutions
+in order for the equation numbers to be stable.
+A separate counter for equations within solutions is enabled by default.
+It can be disabled by:
+%
+\begin{center}
+|\exercisestyle{solutionequation=false}|
+\end{center}
+%
+This option prepends the letter `S' to equation
+numbers within solutions which are counted separately;
+the display can be configured differently, see \secref{sec:layout}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutionbelow}
+\DescribeMacro{\insertsolutions}
+The package allows to collect solutions
+and defer their display to particular locations:
+%
+\begin{center}
+|\exercisestyle{solutionbelow=|\textit{pos}|}|
+\end{center}
+%
+The available choices for \textit{pos} are
+to display solutions where they are defined (|here|),
+defer them to the end of the current subproblem (|subproblem|),
+problem (|problem|) or sheet (|sheet|)
+or display them at a manually chosen location (|manual|).
+Note that typically solutions are defined at the end of a (sub)problem
+and therefore the choice |here| is similar to (|sub|)|problem|.
+The latter form, however, makes sure that a solution is positioned
+\emph{after} the (sub)problem block
+such that it does not inherit the layout (e.g.\ indentation)
+of the latter even if it is defined within this block.
+In |manual| mode, all solutions are collected (with appropriate headers)
+until they are output by the directive |\insertsolutions|.
+If no solutions are stored in the buffer
+(or if the mode is not |manual|), |\insertsolutions| has no effect.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\readsolutions}
+Another option to handle solutions is to write them to a file
+for later use.
+Writing to a file is initiated by:
+%
+\begin{center}
+|\writesolutions[|\textit{filename}|]|
+\end{center}
+%
+The optional argument describes the filename as \textit{filename}|.sol|;
+no argument defaults to the main tex filename as |\jobname.sol|.
+This mode overrides the |solutionbelow| behaviour described above;
+all subsequent solutions are written to the file.
+The file is closed by |\closesolutions| and the display of solutions
+returns to manual mode.
+It is not necessary to close a file as it will be closed
+automatically by reading from a file, writing to another file
+or by the end of the document.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\readsolutions}
+Solutions are read from a file by:
+%
+\begin{center}
+|\readsolutions[|\textit{filename}|]|
+\end{center}
+%
+This command outputs a sectional title
+and reads the file via |\input{|\textit{filename}|.sol}|.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Metadata}
+\label{sec:metadata}
+
+In a collection of exercise problems
+it makes sense to keep track of metadata
+for the overall collection as well as for individual problems
+and potentially display some of them.
+The framework defines a standard set of metadata fields
+and offers functionality to add more specialised metadata fields.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exercisedata}
+Global metadata is specified by the command:
+%
+\begin{center}
+|\exercisedata{|\textit{data}|}|
+\end{center}
+%
+The argument \textit{data}
+is a comma-separated list of metadata specifications
+in the form \textit{key}|={|\textit{value}|}|.
+The standard set of global metadata keys consists of:
+%
+\begin{itemize}
+\item |author|:
+principal author(s) of the exercise collection;
+also invokes the \LaTeX{} command |\author|;
+will be written to pdf documents.
+\item |title|:
+title of the exercise collection;
+also invokes the \LaTeX{} command |\title|;
+will be written to pdf documents.
+\item |date|:
+date of the exercise collection;
+also invokes the \LaTeX{} command |\date|;
+will be written to pdf documents.
+\item |subject|:
+subject area of the exercise collection;
+will be written to pdf documents.
+\item |keyword|:
+keyword(s) for the exercise collection;
+will be written to pdf documents.
+\item |course|:
+title of the course (class, lecture, module, \ldots)
+for the exercise collection.
+\item |institution|:
+institution (school, department, institute, university, \ldots)
+offering the course or exercise collection.
+\item |instructor|:
+instructor(s) for the course or exercise;
+this field refers to person(s) who organise
+the corresponding course or exercises
+whereas |author| refers to the principal creator of the material.
+\item |period|:
+period (year, season, date, term identifier, \ldots)
+of the corresponding course.
+\item |material|:
+type of material
+(exercises, homework assignments, exam, quizzes, solutions, \ldots).
+\end{itemize}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defexercisedata}
+Additional custom fields for global metadata can be created with:
+%
+\begin{center}
+|\defexercisedata{|\textit{key}|}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getexercisedata}
+\DescribeMacro{\exercisedataempty}
+Global metadata should typically be specified
+somewhere at the top of the main document,
+and it can be inserted wherever needed.
+There are two commands to read and process metadata.
+To insert the value of metadata field \textit{key} use:
+%
+\begin{center}
+|\getexercisedata{|\textit{key}|}|
+\end{center}
+%
+In some situations the output should depend on whether
+a metadata has been filled
+(e.g.\ to fill a default value or to display something else instead).
+This can be checked with the conditional:
+%
+\begin{center}
+|\exercisedataempty{|\textit{key}|}|%
+  |{|\textit{empty code}|}{|\textit{filled code}|}|
+\end{center}
+%
+The \textit{empty code} is executed if no value
+or an empty value has been specified;
+otherwise the \textit{filled code} is executed.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{sheet}
+\DescribeMacro{problem}
+The package offers a similar mechanism to describe and use metadata
+for sheets and problems:
+%
+\begin{center}
+|\begin{sheet}[|\textit{opts}|]|
+|\begin{problem}[|\textit{opts}|]|
+\end{center}
+%
+The argument \textit{opt}
+is a comma-separated list which can contain metadata specifications
+in the form \textit{key}|={|\textit{value}|}|.
+The standard set of metadata keys for sheets consists of:
+%
+\begin{itemize}
+\item |due|:
+indication of the due date for the exercise sheet.
+\item |handout|:
+indication of the handout date for the exercise sheet.
+\item |title|:
+specifies a title for the sheet;
+when reading value (see below), returns composed title;
+untitled sheets will be displayed by their number;
+title will be written to pdf documents.
+\item |rawtitle| (for reading only):
+contains the raw title as specified by |title|.
+\item |author|:
+author(s) of the sheet;
+will be written to pdf documents.
+\item |editor|:
+editor(s) of the sheet; this field refers to a person
+who makes adjustments to the sheet
+whereas |author| refers to the creator of the sheet.
+\item |editdate|:
+indication of the date when the sheet was last edited.
+\end{itemize}
+%
+The standard set of metadata keys for problems consists of:
+%
+\begin{itemize}
+\item |title|:
+specifies a title for the problem;
+when reading value (see below), returns composed title;
+untitled problems will be displayed by their number.
+\item |rawtitle| (for reading only):
+contains the raw title as specified by |title|.
+\end{itemize}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defsheetdata}
+\DescribeMacro{\getsheetdata}
+\DescribeMacro{\sheetdataempty}
+\DescribeMacro{\defproblemdata}
+\DescribeMacro{\getproblemdata}
+\DescribeMacro{\problemdataempty}
+Metadata for sheets can be used in the same way as the global metadata.
+The following directives are analogous to |\defexecisesdata|,
+|\getproblemdata| and |\problemdataempty|:
+%
+\begin{center}
+\begin{tabular}{l}
+|\defsheetdata{|\textit{key}|}|\\
+|\getsheetdata{|\textit{key}|}|\\
+|\sheetdataempty{|\textit{key}|}|%
+  |{|\textit{empty code}|}{|\textit{filled code}|}|\\[1ex]
+|\defproblemdata{|\textit{key}|}|\\
+|\getproblemdata{|\textit{key}|}|\\
+|\problemdataempty{|\textit{key}|}|%
+  |{|\textit{empty code}|}{|\textit{filled code}|}|
+\end{tabular}
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{pdfdata}
+\DescribeMacro{\writeexercisedata}
+The most relevant metadata can be written to
+the metadata section of pdf files
+(using pdf\LaTeX{} and the package \textsf{hyperref}
+whenever loaded).
+This feature is configured by:
+%
+\begin{center}
+|\exercisesetup{pdfdata|[|=auto|\textbar|manual|%
+  \textbar|sheet|\textbar|off|]|}|
+\end{center}
+%
+The option |auto| writes the global metadata
+|title|, |author|, |subject| and |keyword|
+to the corresponding fields in the pdf file.
+To make this work, these must be defined before the
+|\begin{document}| directive.
+The option |manual| allows to manually write these metadata
+by the command |\writeexercisedata|.
+It should be issued after the metadata have been set,
+but before any content is written to the pdf file.
+In other words, it can be anywhere in the document preamble
+directly after |\begin{document}|,
+or following a couple of content-free definitions at the beginning
+of the document body (in case the metadata should be set
+within the document body for some reason).
+The option |sheet| writes out the metadata
+at the beginning of the first |sheet| environment
+(which should follow |\begin{document}| without any content in between).
+This option is primarily for filling the
+|author| and |title| fields with metadata
+of a sheet rather than a collection of exercises.
+Note that if no |author| is defined for the sheet,
+the global metadata |author| is used.
+The option |off| disables all writing of metadata.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{problem}
+\DescribeMacro{subproblem}
+\DescribeMacro{solution}
+There is an additional mechanism to keep track of metadata
+for problems, subproblems and solutions
+which can be displayed in the opening line of these entities.
+Displayed metadata serve two purposes:
+they are used to describe the quality of a problem
+or they are intended for internal documentation purposes.
+Their output can be controlled individually,
+e.g.\ only in development versions of a document.
+Note that specifying a key more than once
+will display the content multiple times
+in the order in which they are encountered.
+Displayed metadata are specified
+at the top of the corresponding environment:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{problem}[|\textit{opts}|]|\\
+|\begin{subproblem}[|\textit{opts}|]|\\
+|\begin{solution}[|\textit{opts}|]|
+\end{tabular}
+\end{center}
+%
+
+The standard set of displayed metadata keys consists of:
+%
+\begin{itemize}
+\item |author|:
+author(s) of the problem (or subproblem, solution).
+\item |editor|:
+editor(s) of the problem; this field refers to a person
+who has made adjustments to the problem
+whereas |author| refers to the creator of the problem.
+\item |source|:
+source of the problem;
+in case the problem has been taken from elsewhere
+(conceptually or literally).
+\item |difficulty|:
+indication of the level of difficulty of the problem.
+\item |keyword|:
+keyword(s) for the problem;
+\item |comment|:
+some comment on the problem.
+\item |optional|
+(enabled by default):
+whether addressing the problem is mandatory or optional;
+by default the text will be displayed after the title
+in italic shape.
+\end{itemize}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{extdata}
+Further displayed metadata keys
+are defined by the package option |extdata|, see \secref{sec:options}:
+%
+\begin{itemize}
+\item |review|:
+field to review the aspects of the problem
+(quality, length, appropriateness, difficulty, \ldots).
+\item |recycle|:
+indication of previous instances where this problem was used.
+\item |timesolve|:
+indication of the time needed to solve this problem (or subproblem).
+\item |timepresent|:
+indication of the time needed to present this problem
+(or subproblem, solution).
+\end{itemize}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\showprobleminfo}
+The display of the above metadata fields for a problem
+(or subproblem, solution) is controlled by:
+%
+\begin{center}
+|\showprobleminfo{|\textit{keys}|}|
+\end{center}
+%
+Here \textit{keys} is a comma-separated list of keys to
+be activated (\textit{key} or \textit{key}|=true|)
+or deactivated (\textit{key}|=false|).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defprobleminfo}
+Displayable metadata can be defined or adjusted by:
+%
+\begin{center}
+|\defprobleminfo{|\textit{key}|}{|\textit{code}|}|
+\end{center}
+%
+Here \textit{key} specifies the metadata field and
+\textit{code} the code to display this type of metadata
+where the argument |#1| represents the data to be displayed.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{insertprobleminfo}
+\DescribeMacro{insertsubprobleminfo}
+\DescribeMacro{insertsolutioninfo}
+\DescribeMacro{\addprobleminfo}
+\DescribeMacro{\addprobleminfo*}
+Additional information can be injected into the opening line
+of problems and solutions by the definitions:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseconfig{insertprobleminfo}{|\textit{code}|}|\\
+|\exerciseconfig{insertsubprobleminfo}{|\textit{code}|}|\\
+|\exerciseconfig{insertsolutioninfo}{|\textit{code}|}|
+\end{tabular}
+\end{center}
+%
+The hook code \textit{code} will be called after processing
+the environment arguments. Information can be added to the opening line by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\addprobleminfo{|\textit{info}|}|\\
+|\addprobleminfo*{|\textit{info}|}|
+\end{tabular}
+\end{center}
+%
+The unstarred command adds information at the end of the opening line,
+the starred version at the beginning (but after the title or identifier).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Points}
+\label{sec:points}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{points}
+Exercise problems or certain parts of them
+can be credited with points (credits, awards, \ldots).
+The package provides an interface to specify and manage such points.
+Points are declared by the option |points=|\textit{points}
+for the environments |sheet|, |problem| and |subproblem|.
+These numbers will be printed to the opening line of
+problems and subproblems.
+
+Note that the points should normally be integer numbers.
+Fractional points are permissible as well,
+but the internal storage by the \TeX{} engine is somewhat limited,
+so that only fractions with powers of two as denominators
+(.5, multiples of .25, .125, .0625, \ldots) are reliable.
+More general fractional decimal numbers such as multiples of 0.2
+will be subject to rounding errors and will not display nicely.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{pointsat}
+\DescribeMacro{subpointsat}
+The location where points of problems and subproblems
+shall be displayed can be adjusted individually by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\problemstyle{points=start|\textbar|start*|\textbar|margin|%
+  \textbar|end|\textbar|manual|\textbar|off}|\\
+|\problemstyle{subpoints=start|\textbar|start*|\textbar|margin|%
+  \textbar|end|\textbar|manual|\textbar|off}|
+\end{tabular}
+\end{center}
+%
+The default values are |start| and |end| for problems and subproblems,
+respectively.
+The option |start| displays points at
+the very end of the opening line;
+the option |start*| displays them at the start of it.
+The option |end| displays points at the end of the
+problem or subproblem text.
+The option |margin| displays points in the margin.
+The option |manual| displays points at a manually chosen location
+specified by the directive |\showpoints|.
+Note that |\showpoints| can also be used for the option |end|
+to display the points prematurely
+(e.g.\ if the text ends with a displayed equation,
+it may make sense to display the points just before the equation).
+The option |off| disables the display of points.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getsheetdata}
+Points for sheets are only stored by the package;
+they must displayed manually.
+Within the corresponding |sheet| environment
+the points can be accessed by:
+%
+\begin{center}
+|\getsheetdata{points}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getsheetpoints}
+\DescribeMacro{\getproblempoints}
+The package allows to read the point totals
+for other sheets and problems:
+%
+\begin{center}
+\begin{tabular}{l}
+|\getsheetpoints{|\textit{tag}|}|\\
+|\getproblempoints{|\textit{tag}|}|
+\end{tabular}
+\end{center}
+%
+Here \textit{tag} is the tag assigned to the corresponding sheet or problem,
+see \secref{sec:labels}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\awardpoints}
+Grading instructions with points to be awarded
+can be specified in the solution text by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\awardpoints[|\textit{details}|]{|\textit{points}|}|\\
+|\awardpoints*[|\textit{details}|]{|\textit{points}|}|
+\end{tabular}
+\end{center}
+%
+Here \textit{details} is an optional text with further details,
+e.g.\ to explain under which conditions
+these points are to be awarded.
+The starred form is used to specify optional points or alternative paths
+with alternative grading instructions.
+These points will be marked and not be used for the computation of a total.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{warntext}
+The package attempts to add up
+the points of subproblems to the problem total
+and likewise the points of problems to the sheet total.
+The package also performs some sanity checks on the provided numbers:
+If points are specified for both subproblems and problems
+or for both problems and sheets, they will be compared.
+Also the points within solutions (excluding optional or alternative points)
+are added up and compared to the corresponding problem or subproblem.
+Furthermore the package checks whether points
+are defined for all subproblems within a problem
+or all problems within a sheet.
+Mismatches are reported as package warnings.
+As point mismatches can be rather severe,
+there is an option to write such warnings directly into
+the output document (to be removed before distribution):
+%
+\begin{center}
+|\exercisesetup{warntext|[|=true|\textbar|false|]|}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{fracpoints}
+The package offers pretty display of fractional points
+with denominators 2, 4 and 8 by writing the decimal part
+as a fraction, e.g.\ 1.75 $\to$ 1$^3\mskip-4mu/\mskip-2mu_4$.
+This feature is enabled by:
+%
+\begin{center}
+|\exercisestyle{fracpoints}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Labels and Tags}
+\label{sec:labels}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{label}
+\LaTeX{} provides labels to make references to remote parts of the text.
+Labels can be set as usual by |\label{|\textit{label}|}| within the
+|problem|, |subproblems| and |sheet| environments.
+Alternatively, they can be specified
+as the environment option:
+%
+\begin{center}
+|label={|\textit{label}|}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{tag}
+\DescribeMacro{\sheettag}
+\DescribeMacro{\problemtag}
+The package provides an additional mechanism to tag sheets and problems.
+Each |sheet| and each |problem| can be assigned a unique tag \textit{tag} by
+the environment option:
+%
+\begin{center}
+|tag={|\textit{tag}|}|
+\end{center}
+%
+This tag is used for reading point totals
+as described in \secref{sec:points}.
+Furthermore, the macro |\sheettag| or |\problemtag|
+is set to the tag \textit{tag} within the current environment.
+If no tag is specified it matches the number of the sheet or problem;
+note that this number can change by reordering sheets and problems
+and therefore it should not be used to identify the entity from
+other parts of the document.
+
+A useful application for tags is to encapsulate labels
+within individual sheets and problems
+which are part of a collection of exercises.
+Labels which are composed as
+|\sheettag-|\textit{label} or
+|\problemtag-|\textit{label}
+can be considered local and will not clash with labels
+defined within a different environment.
+Within the same sheet or problem, local labels can be accessed
+by the same construction.
+They can also be accessed from remote parts of the document by fully
+expanding |\sheettag| or |\problemtag| for the desired target environment.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{autolabelsheet}
+\DescribeMacro{autolabelproblem}
+If unique tags are specified, the package can automatically create labels
+for sheets (|sheet:|\textit{tag}) and problems (|prob:|\textit{tag}) by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exercisesetup{autolabelsheet|[|=true|\textbar|false|]|}|\\
+|\exercisesetup{autolabelproblem|[|=true|\textbar|false|]|}|
+\end{tabular}
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Layout}
+\label{sec:layout}
+
+The package provides a large number of parameters to adjust the
+display of exercises to a desired layout.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exerciseconfig}
+Configuration settings are declared and modified by the command:
+%
+\begin{center}
+|\exerciseconfig{|\textit{key}|}[|\textit{narg}|]{|\textit{value}|}|
+\end{center}
+%
+Here \textit{key} is a key and \textit{value} is its assigned value.
+Configuration options can also be macros with arguments in which case
+\textit{narg} is the number of arguments and \textit{value}
+is the macro definition using arguments |#|\textit{n}.
+The command |\exerciseconfig| therefore is analogous to
+|\|(|re|)|newcommand| except that the definitions are
+encapsulated by the package and any previous definition
+is overwritten without checking.
+
+\DescribeMacro{\exerciseconfigappend}
+\DescribeMacro{\exerciseconfigprepend}
+In some cases it may be useful to be able to
+append or prepend to a (parameterless) definition by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseconfigappend{|\textit{key}|}{|\textit{value}|}|\\
+|\exerciseconfigprepend{|\textit{key}|}{|\textit{value}|}|
+\end{tabular}
+\end{center}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getexerciseconfig}
+\DescribeMacro{\exerciseconfigempty}
+Configuration definitions can be read by:
+%
+\begin{center}
+|\getexerciseconfig{|\textit{key}|}|[\textit{arguments}]
+\end{center}
+%
+The number of arguments after |{|\textit{key}|}|
+must match the optional argument \textit{nargs} of the definition.
+Furthermore, it can be checked whether a configuration definition
+is empty:
+%
+\begin{center}
+|\exerciseconfigempty{|\textit{key}|}|%
+  |{|\textit{empty code}|}{|\textit{filled code}|}|
+\end{center}
+%
+The \textit{empty code} is executed if no value
+or an empty value has been specified.
+Otherwise the \textit{filled code} is executed.
+
+The package defines numerous layout configuration options.
+They are listed along with their original definition
+and a brief description in \secref{sec:imp-config}.
+They include options to:
+%
+\begin{itemize}
+\item
+adjust the language for the principal entities of this package
+like `sheet(s)', `problem(s)', `solution(s)', `points(s)';
+\item
+adjust the fonts styles of various parts of the text;
+\item
+adjust the spacing above, below, between various elements;
+\item
+define code to process data and insert text at various locations;
+\item
+compose text to be used in various situations;
+\item
+adjust the appearance of counters;
+\item
+adjust some other behaviour of the package.
+\end{itemize}
+%
+The following will highlight only few examples.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{insertsheettitle}
+An important setting is:
+%
+\begin{center}
+|\exerciseconfig{insertsheettitle}{|\textit{code}|}|
+\end{center}
+%
+The code \textit{code} is meant to print the title
+or header of an exercise sheet.
+The minimalistic default code |\centerline{\getsheetdata{title}}|
+merely prints the sheet title ``Sheet \#'' at the centre of a line.
+Commonly, one would replace this by a more elaborate header
+(potentially with some more information,
+appealing layout, logos, \ldots).
+In order to design a header template,
+it makes sense to retrieve data
+via |\getexercisedata| and |\getsheetdata|
+described in \secref{sec:metadata}.
+Likewise |\exercisedataempty| and |\sheetdataempty|
+can be used to display default values or alternative data
+if some particular data is not provided.
+An example is given by the |plainheader| extended style option
+defined in \secref{sec:imp-styles}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{composetitleproblem}
+Another noteworthy example is |composetitleproblem|
+to compose the title for a problem. It takes two parameters,
+the number and the title.
+The (somewhat simplified) default declaration is:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseconfig{composetitleproblem}[2]{\exerciseifempty{#2}|\\
+|  {\getexerciseconfig{termproblem}|\\
+|   \getexerciseconfig{composeitemproblem}{#1}}|\\
+|  {\getexerciseconfig{composeitemproblem}{#1} #2}}|
+\end{tabular}
+\end{center}
+%
+This checks whether the title is empty.
+If no title is given use ``Problem \#.'',
+otherwise use ``\#. \textit{title}''.
+Here the term ``Problem'' is made abstract
+by the configuration |termproblem|
+(e.g.\ to support internationalisation)
+and the problem number is further composed obtained by
+the configuration |composeitemproblem|
+which takes the bare number as argument
+and returns it followed by a dot.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exerciseifempty}
+\DescribeMacro{\exerciseifnotempty}
+Handy conditionals command to check
+whether an expression \textit{expr} is empty (or pure whitespace) is:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseifempty{|\textit{expr}|}|%
+  |{|\textit{empty code}|}{|\textit{filled code}|}|\\
+|\exerciseifnotempty{|\textit{expr}|}|%
+  |{|\textit{filled code}|}|
+\end{tabular}
+\end{center}
+%
+Their main purpose is to test
+whether some provided expression \textit{expt} is empty.
+They expand to the common \TeX{} constructs
+|\if&#1&#2\else#3\fi| and |\if&#1&\else#2\fi|
+which work assuming that \textit{expr} is not too exotic
+(e.g.\ it should not start with the character `|&|'
+and other special \TeX{} characters or macros are potentially dangerous).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Exercise Styles}
+\label{sec:styles}
+
+The package provides a mechanism to define exercise styles
+which customise the display of exercises in some coordinated fashion.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exercisestyle}
+Style(s) are activated by the command:
+%
+\begin{center}
+|\exercisestyle{|\textit{styles}|}|
+\end{center}
+%
+Here \textit{styles} is a comma-separated list of styles,
+where each style is given by a pair \textit{style}[|={|\textit{argument}|}|].
+The package defines a couple of standard styles:
+%
+\begin{itemize}
+\item |solutionbelow=|\textit{pos}
+(can take values |here|, |subproblem|, |problem|, |sheet| and |manual|;
+initially set to |subproblem|) --
+positions the solutions below the indicated blocks;
+see \secref{sec:solutions} for details.
+
+\item |pointsat=|\textit{pos}
+(can take values |start|, |start*|, |margin|, |end| and |manual|;
+initially set to |start|) --
+displays points in problems at the indicated location;
+see \secref{sec:points} for details.
+
+\item |subpointsat=|\textit{pos}
+(can take values |start|, |start*|, |margin|, |end| and |manual|;
+initially set to |end|) --
+displays points in subproblems at the indicated location;
+see \secref{sec:points} for details.
+
+\item |problemby={|\textit{counter}|}| --
+number problems with the prefix \textit{counter},
+i.e.\ reset the problem counter whenever \textit{counter} increases
+and use a composite label \textit{counter}|.|\textit{problem}
+to identify problems.
+
+\item |equationby={|\textit{counter}|}| --
+number the dedicated equation counters for sheets, problems and solutions
+with the prefix \textit{counter}.
+
+\item |problembysheet| --
+number problems by sheet.
+
+\item |equationbysheet| --
+number equations by sheet.
+
+\item |pagebysheet| --
+number pages by sheet and denote pages by \textit{sheet}|.|\textit{page};
+this style is useful to generate stable page numbers for
+a collection of sheets.
+
+\item |sheetequation|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+use a dedicated equation counter within sheets.
+
+\item |problemequation|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+use a dedicated equation counter within problems.
+
+\item |solutionequation|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |true|) --
+use a dedicated equation counter within solutions.
+
+\item |fracpoints|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+display fractional points for denominators 2, 4, 8;
+see \secref{sec:points} for details.
+
+\item |twoside|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable two-sided layout;
+in two-sided layout, sheets will start on odd pages
+and empty pages are added at the end of sheets
+to produce an even number of pages.
+
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{extstyle}
+Further exercise styles
+are defined by the package option |extstyle|, see \secref{sec:options}:
+%
+\begin{itemize}
+\item |plainheader| --
+define a plain sheet header to display
+some essential exercise and sheet data:
+|course|, |institution|, |instructor|, |period| (optional), sheet |title|,
+see \secref{sec:metadata};
+the line below the header, font styles and spaces can be adjusted,
+see the definition in \secref{sec:imp-styles}.
+
+\item |contents| --
+display sheets and problems in the table of contents
+(as sections and subsections).
+
+\item |solutionsf| --
+display solutions in sans serif font family.
+
+\item |solutiondimproblem| --
+dim the problem text whenever solutions are displayed.
+
+\item |solutionsep| --
+separate the solutions from the remaining text by horizontal lines.
+
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defexercisestyle}
+Custom styles can be defined by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\defexercisestyle{|\textit{style}|}{|\textit{init}|}|\\
+|\defexercisestylearg[|\textit{default}|]{|\textit{style}|}{|\textit{init}|}|
+\end{tabular}
+\end{center}
+%
+This feature can be used to predefine certain aspects of
+the exercises layout.
+For example, different default page layouts could be declared in this way.
+The first version declares a style which is
+initialised by the code \textit{item} upon activation by
+|\exercisestyle{|\textit{style}[|=true|]|}|.
+Note that |\exercisestyle{|\textit{style}|=false}| does nothing.
+The second version declares a style which is activated by
+|\exercisestyle{|\textit{style}[|={|\textit{arg}|}|]|}|
+and which calls \textit{item} with the argument |#1| referring to \textit{arg}
+(or \textit{default} if no argument is given).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Package Options}
+\label{sec:options}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exercisesetup}
+Features and options of general nature can be selected by the commands:
+%
+\begin{center}
+\begin{tabular}{rl}
+&|\usepackage[|\textit{opts}|]{exframe}|
+\\
+or&|\PassOptionsToPackage{|\textit{opts}|}{exframe}|
+\\
+or&|\exercisesetup{|\textit{opts}|}|
+\end{tabular}
+\end{center}
+%
+|\PassOptionsToPackage| must be used before |\usepackage|;
+|\exercisesetup| must be used afterwards.
+\textit{opts} is a comma-separated list of options.
+
+The following options are available only when
+loading the package, i.e.\ they will not work
+within |\exercisesetup|:
+%
+\begin{itemize}
+\item |extdata|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+define some more advanced metadata entries.
+
+\item |extstyle|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+define some more advanced styles.
+
+\item |problemenv=|\textit{name} --
+redefine environment name |problem|.
+This and the following alike options may be useful in
+quickly adjusting existing sources to
+the \textsf{exframe} framework
+if the original framework works similarly
+and no special features are used.
+Otherwise, it is highly advisable to leave the
+names of environments and counters
+defined by the package untouched.
+
+\item |subproblemenv=|\textit{name} --
+redefine environment name |subproblem|.
+
+\item |solutionenv=|\textit{name} --
+redefine environment name |solution|.
+
+\item |sheetenv=|\textit{name} --
+redefine environment name |sheet|.
+
+\item |problemcounter=|\textit{name} --
+redefine counter name |problem|.
+
+\item |subproblemcounter=|\textit{name} --
+redefine counter name |subproblem|.
+
+\item |solutioncounter=|\textit{name} --
+redefine counter name |solution|.
+
+\item |sheetcounter=|\textit{name} --
+redefine counter name |sheet|.
+
+\end{itemize}
+%
+
+The following options can be specified by all three methods described above:
+%
+\begin{itemize}
+\item |solutions|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+Enable/disable display of solutions.
+Sets the conditional |\ifsolutions| accordingly.
+
+\item |pdfdata|[|=auto|\textbar|manual|\textbar|sheet|\textbar|off|]
+(no value implies |auto|, initially set to |auto|) --
+control writing most relevant metadata to pdf files;
+has no effect without package \textsf{hyperref}.
+
+\item |lineno|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable writing of line numbers as comments
+into solution files.
+
+\item |twoside|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable two-sided layout;
+see \secref{sec:styles} for details.
+
+\item |solutionhref|[|=true|\textbar|true|]
+(no value implies |true|, initially set to |false|) --
+enable/disable use of hyper-references from solutions
+to the corresponding problems;
+has no effect without package \textsf{hyperref}.
+
+\item |warntext|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable writing of relevant warning messages
+(points mismatch, point sums require update)
+into the document output for easier detection.
+
+\item |autolabelsheet|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable automatically assigning labels
+(|sheet:\sheettag|; can be adjusted)
+to sheets according to their tag |\sheettag|.
+
+\item |autolabelproblem|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable automatically assigning labels
+(|prob:\problemtag|; can be adjusted)
+to problems according to their tag |\problemtag|.
+
+\end{itemize}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Information}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Copyright}
+
+Copyright \copyright{} 2011--2019 Niklas Beisert
+
+This work may be distributed and/or modified under the
+conditions of the \LaTeX{} Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in
+  \url{http://www.latex-project.org/lppl.txt}
+and version 1.3 or later is part of all distributions of \LaTeX{}
+version 2005/12/01 or later.
+
+This work has the LPPL maintenance status `maintained'.
+
+The Current Maintainer of this work is Niklas Beisert.
+
+This work consists of the files |README.txt|, |exframe.ins| and |exframe.dtx|
+as well as the derived files |exframe.sty|, |exfsmp1.tex| and |exframe.pdf|.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Files and Installation}
+
+The package consists of the files:
+%
+\begin{center}
+\begin{tabular}{ll}
+    |README.txt|   & readme file \\
+    |exframe.ins|  & installation file \\
+    |exframe.dtx|  & source file \\
+    |exframe.sty|  & package file \\
+    |exfsmp1.tex|  & sample file \\
+    |exframe.pdf|  & manual
+\end{tabular}
+\end{center}
+%
+The distribution consists of the files
+|README.txt|, |exframe.ins| and |exframe.dtx|.
+%
+\begin{itemize}
+\item
+Run (pdf)\LaTeX{} on |exframe.dtx|
+to compile the manual |exframe.pdf| (this file).
+\item
+Run \LaTeX{} on |exframe.ins| to create the package |exframe.sty|
+and the sample |exfsmp1.tex|.
+Copy the file |exframe.sty| to an appropriate directory of your \LaTeX{}
+distribution, e.g.\ \textit{texmf-root}|/tex/latex/exframe|.
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Related Packages}
+
+The package makes use of other packages available at CTAN:
+\begin{itemize}
+\item
+This package relies on some functionality of the package \textsf{verbatim}
+to read verbatim code from the \LaTeX{} source without expansion of macros.
+Compatibility with the \textsf{verbatim} package
+has been tested with v1.5q (2014/10/28).
+\item
+This package uses the package
+\href{http://ctan.org/pkg/xkeyval}{\textsf{xkeyval}}
+to process the options for the package, environments and macros.
+Compatibility with the \textsf{xkeyval} package
+has been tested with v2.7a (2014/12/03).
+\item
+This package can use the package
+\href{http://ctan.org/pkg/hyperref}{\textsf{hyperref}}
+to include hyperlinks between problems and solutions.
+Compatibility with the \textsf{hyperref} package
+has been tested with v6.88e (2018/11/30).
+\item
+This package can use the package
+\href{http://ctan.org/pkg/amstext}{\textsf{amstext}}
+(which is automatically loaded by \textsf{amsmath})
+to display text within equations.
+Compatibility with the \textsf{amstext} package
+has been tested with v2.01 (2000/06/29).
+\item
+This package uses the command |\currfilename|
+provided by the package \textsf{currfile} (if available and loaded)
+to indicate the \LaTeX{} source file in the generated metapost file.
+Compatibility with the \textsf{currfile} package
+has been tested with v0.7c (2015/04/23).
+\item
+This package cooperates well with the package
+\href{http://ctan.org/pkg/childdoc}{\textsf{childdoc}}
+to produce individual sheets, single problems
+as well as a collection of all exercises.
+\end{itemize}
+
+There are several other \LaTeX{} packages
+which offer a similar functionality
+varying largely in scope and sophistication:
+%
+\begin{itemize}
+\item
+The package \href{http://ctan.org/pkg/exsheets}{\textsf{exsheets}}
+and its successor \href{http://ctan.org/pkg/xsim}{\textsf{xsim}}
+provide a \LaTeX{} 3 style for typesetting exercises with solutions.
+They offer options to
+hide or delay solutions,
+print only specific problems,
+deal with points
+specify metadata,
+handle exercise collections,
+as well as some more specific options.
+They allow to adjust the layout and choose among predefined ones.
+\item
+The package \href{http://ctan.org/pkg/exercise}{\textsf{exercise}}
+provides a style for typesetting exercises with solutions.
+It offers many options to
+hide or delay solutions,
+print only specific problems,
+specify some metadata
+as well as some more specific options.
+It allows to customise the layout.
+\item
+The package \href{http://ctan.org/pkg/exercises}{\textsf{exercises}}
+provides a style for typesetting exercises with solutions.
+It offers options to hide solutions and deal with points.
+It allows basic customisation of the layout.
+\item
+The package \href{http://ctan.org/pkg/exam}{\textsf{exam}}
+provides a document class for typesetting exams conveniently.
+It offers many options to hide solutions, deal with points
+and deal with other exam-specific tasks.
+It allows to adjust the layout and choose among predefined ones.
+\item
+The package \href{http://ctan.org/pkg/probsoln}{\textsf{probsoln}}
+provides a style for typesetting exercises with solutions
+which are stored in a collection.
+It offers options to
+hide solutions
+and to assemble problems from an external collection.
+\item
+The packages
+\href{http://ctan.org/pkg/uebungsblatt}{\textsf{uebungsblatt}},
+\href{http://ctan.org/pkg/uassign}{\textsf{uassign}},
+\href{http://ctan.org/pkg/mathexam}{\textsf{mathexam}},
+\href{http://ctan.org/pkg/exsol}{\textsf{exsol}},
+\href{https://github.com/mbauman/homework}{\textsf{homework}},
+\href{https://gist.github.com/jhwilson/1278588}{\textsf{jhwhw}}
+provide basic functionality for somewhat more particular situations.
+\end{itemize}
+%
+See CTAN categories
+\href{http://ctan.org/topic/exercise}{\textsf{exercise}}
+and \href{http://ctan.org/topic/exam}{\textsf{exam}}
+for further up-to-date packages.
+
+The philosophy of the present package is to
+define a low-level framework to describe exercises with solutions
+to be used in various situations.
+The aim is to provide the means to describe the content
+(problems, solutions, sheets) in a simple fashion
+and separate it from the various layout definitions and choices
+which will define the appearance of the content.
+The interface was designed to reduce potential conflict
+with other packages and definitions.
+The package itself does not define an elaborate layout,
+but it provides means to adjust it in many ways and
+to predefine custom layout schemes.
+The package offers most of the functionality of the above packages,
+but (presently) misses out on some more advanced features,
+see \secref{sec:suggestions}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Feature Suggestions}
+\label{sec:suggestions}
+
+The following is a list of features which may be useful for future
+versions of this package:
+%
+\begin{itemize}
+\item
+Option to hide problem text while maintaining access to embedded solutions
+(for a version containing only solutions)
+or to postpone problems (for collecting them in an exercises section):
+this is difficult to implement because the problem block
+cannot simply be discarded, but must be scanned very carefully
+for the embedded solution.
+\item
+Provide an example with multiple sheets in the same document
+such that the sheet can be compiled individually or as a collection.
+\item
+Define structures for multiple-choice questions.
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Revision History}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.0:} 2019/01/16
+
+\begin{itemize}
+\item
+renamed to |exframe.sty|
+\item
+first version published on CTAN
+\item
+overhaul and streamline interface
+\item
+solution processing remodelled
+\item
+changed metadata handling
+\item
+changed and generalised points handling
+\item
+generalised sectioning layout
+\item
+changed layout specification model
+\item
+insert hyperlinks using \textsf{hyperref}
+\item
+manual, example and installation package added
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v2.0 -- v2.6:} 2014/10/03 -- 2018/11/05
+
+\begin{itemize}
+\item
+changed metadata interface
+\item
+broadened scope
+\item
+added more layout options
+\item
+added more metadata
+\item
+added sheet and problem tags
+\item
+add and remember points
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v1.1 -- v1.6:} 2014/08/07 -- 2014/09/14
+
+\begin{itemize}
+\item
+renamed to |nbprob.sty|
+\item
+added metadata
+\item
+added points
+\item
+added layout configuration
+\item
+removed specific macros
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v1.0 -- v1.02:} 2011/09/23 -- 2013/03/17
+
+\begin{itemize}
+\item
+first version as |problems.cls|
+\item
+dedicated layout and macros for author's exercise sheets
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\appendix
+
+\settowidth\MacroIndent{\rmfamily\scriptsize 0000\ }
+
+ \DocInput{exframe.dtx}
+
+\end{document}
+%</driver>
+% \fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \section{Sample Files}
+% \label{sec:sample}
+%
+% This section provides examples of how to use
+% some of the \textsf{exframe} features.
+% The resulting layout will be somewhat messy
+% due to a random selection of features\ldots
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Single Exercise Sheet}
+% \label{sec:sample1}
+%\iffalse
+%<*sample1>
+%\fi
+%
+% The first (and presently only) example
+% describes a single exercise sheet.
+% The other sheet of the series would be declared
+% in independent documents.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Preamble.}
+%
+% Standard document class:
+%    \begin{macrocode}
+\documentclass[12pt]{article}
+%    \end{macrocode}
+
+% Use package \textsf{geometry} to set the page layout;
+% adjust the paragraph shape:
+%    \begin{macrocode}
+\usepackage{geometry}
+\geometry{layout=a4paper}
+\geometry{paper=a4paper}
+\geometry{margin=2.5cm}
+\parindent0pt
+\parskip0.5ex
+%    \end{macrocode}
+
+% Include \textsf{amsmath}, \textsf{hyperref}
+% and the \textsf{exframe} package:
+%    \begin{macrocode}
+\usepackage{amsmath}
+\usepackage{hyperref}
+\usepackage[extstyle]{exframe}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solutions Switch.}
+%
+% It will be useful to have the switch to turn on/off
+% the display of solutions near the top
+% of the source file, potentially with the opposite setting commented out:
+%    \begin{macrocode}
+\exercisesetup{solutions=true}
+%%\exercisesetup{solutions=false}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Layout Declarations.}
+%
+% The following layout declarations adjust the general layout
+% of exercise sheets. They may as well be moved into an include file.
+%
+% Declare a header for exercise sheets
+% to display several relevant pieces of data;
+% display points total:
+%    \begin{macrocode}
+\exercisestyle{plainheader}
+\exerciseconfig{composeheaderbelowright}{\getsheetdata{points}}%
+%    \end{macrocode}
+
+% Redefine the appearance of some counters;
+% sheets should be labelled by capital roman numerals,
+% subproblems by lowercase roman numerals;
+% declare the widest subproblem item to be expected:
+%    \begin{macrocode}
+\exerciseconfig{countersheet}{\Roman{sheet}}
+\exerciseconfig{countersubproblem}{\roman{subproblem})}
+\exerciseconfig{countersubproblemmax}{vii)}
+%    \end{macrocode}
+
+% Redefine the terms to be used for sheet(s);
+% here, a German version:
+%    \begin{macrocode}
+\exerciseconfig{termsheet}{\"Ubungsblatt}
+\exerciseconfig{termsheets}{\"Ubungsbl\"atter}
+%    \end{macrocode}
+
+% Display points for problems in the margin;
+% change margin display to use the left margin;
+% use the abbreviated form `$n$p.':
+%    \begin{macrocode}
+\exercisestyle{pointsat=margin}
+\reversemarginpar
+\exerciseconfig{composepointsmargin}[1]{#1p.}
+%    \end{macrocode}
+
+% Change the basic font style for all titles to be bold sans-serif:
+%    \begin{macrocode}
+\exerciseconfig{styletitle}{\sffamily\bfseries}
+%    \end{macrocode}
+
+% Add a significant amount of space below problems:
+%    \begin{macrocode}
+\exerciseconfig{skipproblembelow}{1.5cm}
+%    \end{macrocode}
+
+% Display half points as fractions:
+%    \begin{macrocode}
+\exercisestyle{fracpoints}
+%    \end{macrocode}
+% Show solutions below each problem
+% (may try alternatives |subproblem| or |sheet|):
+%    \begin{macrocode}
+\exercisestyle{solutionbelow=problem}
+%    \end{macrocode}
+% Separate solutions by horizontal lines (extended style):
+%    \begin{macrocode}
+\exercisestyle{solutionsep}
+%    \end{macrocode}
+
+% Add course name to sheet title metadata:
+%    \begin{macrocode}
+\exerciseconfig{composemetasheet}[2]{\getexercisedata{course},
+  \exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
+%    \end{macrocode}
+
+% Set title and author for pdf metadata:
+%    \begin{macrocode}
+\exercisesetup{pdfdata=sheet}
+\exercisedata{title=%
+  {\getexercisedata{course}, \getexercisedata{material}}}
+\exercisedata{author=%
+  {\getexercisedata{instructor}, \getexercisedata{institution}}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Exercise Series Data.}
+%
+% Set some data on the current series:
+%    \begin{macrocode}
+\exercisedata{institution={Katharinen-Volksschule}}
+\exercisedata{course={Mathematik}}
+\exercisedata{instructor={J.\ G.\ B\"uttner}}
+\exercisedata{period={ca.\ 1786}}
+\exercisedata{material={\"Ubungsaufgaben}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Body.}
+%
+%    \begin{macrocode}
+\begin{document}
+%    \end{macrocode}
+
+% Start sheet number 5:
+%    \begin{macrocode}
+\begin{sheet}[number=5]
+%    \end{macrocode}
+
+% Start a problem with a title:
+%    \begin{macrocode}
+\begin{problem}[title={Sums}]
+%    \end{macrocode}
+
+% Some introduction to the problem:
+%    \begin{macrocode}
+This problem deals with sums and series.
+%    \end{macrocode}
+
+% A subproblem with a local label:
+%    \begin{macrocode}
+\begin{subproblem}[points=2,difficulty=simple,label={\problemtag-simplesum}]
+Compute the sum
+\showpoints
+\begin{equation}
+1+2+3.
+\end{equation}
+%    \end{macrocode}
+
+% Provide a solution for the subproblem (within the subproblem block):
+%    \begin{macrocode}
+\begin{solution}
+The result is
+\begin{equation}
+1+2+3=6.
+\end{equation}
+\end{solution}
+%    \end{macrocode}
+
+% End subproblem:
+%    \begin{macrocode}
+\end{subproblem}
+%    \end{macrocode}
+
+% Another subproblem:
+%    \begin{macrocode}
+\begin{subproblem}[points=97,difficulty=lengthy]
+Compute the sum
+\begin{equation}
+1+2+3+\ldots+98+99+100.
+\end{equation}
+Keep calm and calculate!
+%%That ought to keep him occupied for a while
+\end{subproblem}
+%    \end{macrocode}
+
+% Provide a solution for the previous subproblem
+% (layout may differ slightly from declaration within);
+% declare author:
+%    \begin{macrocode}
+\begin{solution}[author={C.\ F.\ Gau\ss}]
+We use the result $1+2+3=6$ from part \ref{\problemtag-simplesum}
+to jumpstart the calculation. The remaining sums yield
+\awardpoints[1 for each remaining sum]{97}
+\begin{equation}
+6+4+5+\ldots+99+100=5050.
+\end{equation}
+Alternatively the summands can be grouped into pairs as follows:
+\begin{align}
+1+100&=101,\\
+2+99&=101,\\
+3+98&=101,\\
+\ldots &\nonumber\\
+50+51&=101.
+\end{align}
+These amount to 50 times the same number 101.
+Therefore the sum equals
+\begin{equation}
+1+2+\ldots+99+100=50\cdot 101=5050.
+\end{equation}
+\textit{Ligget se!} \awardpoints*{97}
+\end{solution}
+%    \end{macrocode}
+
+% Some text between subproblems:
+%    \begin{macrocode}
+You may give the final part a try:
+%    \end{macrocode}
+
+% Final subproblem; this one is optional:
+%    \begin{macrocode}
+\begin{subproblem}[optional={optional}, difficulty={requires inspiration}]
+Compute the series
+\begin{equation}
+1+2+3+\ldots
+\end{equation}
+%    \end{macrocode}
+
+% Provide a solution:
+%    \begin{macrocode}
+\begin{solution}
+The series is divergent, so the result is $\infty$ \awardpoints*{1}.
+\par
+However, after subtracting the divergent part,
+the result clearly is
+\begin{equation}
+\zeta(-1)=-\frac{1}{12}\,,
+\end{equation}
+where the zeta-function $\zeta(s)$ is defined by
+\begin{equation}
+\zeta(s):=\sum_{k=1}^\infty \frac{1}{k^s}\,.
+\end{equation}
+This definition holds only for $s>1$ where the sum is convergent,
+but one can continue the complex analytic function to $s<0$
+\awardpoints*{1.5}.
+\par
+Another way of understanding the result
+is to use the indefinite summation formula
+for arbitrary exponent $s$ in the summand
+(which also follows from the Euler--MacLaurin formula)
+\begin{equation}
+\sum_n n^s
+= \frac{n^{s+1}}{s+1}
+ -\sum_{j=0}^s  \frac{\zeta(j-s)\,s!}{(s-j)!\,j!}\,n^j
+= \ldots - \zeta(-s)\,n^0.
+\end{equation}
+Curiously, the constant term with $j=0$ is just the desired result
+but with the wrong sign
+(in fact, the constant term of an indefinite sum is ambiguous;
+for the claim we merely set $j=0$
+in the expression which holds for others values of $j$)
+\awardpoints*{0.5}.
+In order to understand the sign,
+we propose that the above formula describes the regularised result
+for the sum with limits $+\infty$ and $n$
+\begin{equation}
+\sum_{k=+\infty}^n k^s
+\simeq \frac{n^{s+1}}{s+1}
+ -\sum_{j=0}^s  \frac{\zeta(j-s)\,s!}{(s-j)!\,j!}\,n^j.
+\end{equation}
+Then we flip the summation limits of the desired sum
+to bring it into the above form
+\awardpoints*{0.5}
+\begin{equation}
+\sum_{k=1}^\infty k^s
+= -\sum_{k=\infty}^0 k^s
+\simeq \zeta(-s).
+\end{equation}
+\end{solution}
+%    \end{macrocode}
+
+% End subproblem:
+%    \begin{macrocode}
+\end{subproblem}
+%    \end{macrocode}
+
+% End problem:
+%    \begin{macrocode}
+\end{problem}
+%    \end{macrocode}
+
+% Another problem; this one is untitled:
+%    \begin{macrocode}
+\begin{problem}[points=1, difficulty=insane]
+Show that the equation
+\begin{equation}
+a^3+b^3=c^3
+\end{equation}
+has no positive integer solutions.
+\end{problem}
+%    \end{macrocode}
+
+% A solution can also follow a problem
+% (but the layout may be slightly different,
+% e.g.\ here the space below the problem will
+% appear before the solution):
+%    \begin{macrocode}
+\begin{solution}
+\normalmarginpar
+This is beyond the scope of this example.
+\marginpar{\footnotesize\raggedright does not fit here.\par}
+\end{solution}
+%    \end{macrocode}
+
+% End sheet:
+%    \begin{macrocode}
+\end{sheet}
+%    \end{macrocode}
+
+% End of document body:
+%    \begin{macrocode}
+\end{document}
+%    \end{macrocode}
+%\iffalse
+%</sample1>
+%\fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \section{Implementation}
+% \label{sec:implementation}
+%\iffalse
+%<*package>
+%\fi
+%
+% This section describes the package |exframe.sty|.
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{General Definitions}
+% \label{sec:imp-def}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Required Packages.}
+%
+% The package loads the package
+% \textsf{verbatim} and \textsf{xkeyval}
+% if not yet present.
+% \textsf{verbatim} is used for solution block reading
+% and \textsf{xkeyval} is used for extended options processing:
+%    \begin{macrocode}
+\RequirePackage{verbatim}
+\RequirePackage{xkeyval}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{General Definitions.}
+%
+% \macro{\exf at empty}
+% Define an empty macro for comparison by |\ifx|:
+%    \begin{macrocode}
+\def\exf at empty{}
+%    \end{macrocode}
+
+% \macro{\exf at tmpdim}
+% Define a length for temporary storage:
+%    \begin{macrocode}
+\newlength\exf at tmpdim
+%    \end{macrocode}
+
+% \macro{\exf at exptwo}
+% A macro to conveniently expand the third token in line:
+%    \begin{macrocode}
+\def\exf at exptwo#1{\expandafter#1\expandafter}
+%    \end{macrocode}
+% \macro{\exf at exparg}
+% A macro to conveniently expand the first token
+% of an argument following arbitrary code:
+%    \begin{macrocode}
+\long\def\exf at expswitch#1#2{#2{#1}}
+\long\def\exf at exparg#1#2{\exf at exptwo\exf at expswitch{#2}{#1}}
+%    \end{macrocode}
+% \macro{\exf at csdo}
+% \macro{\exf at csdotwo}
+% Some macros to conveniently expand |\csname| arguments
+% before expanding the macro:
+%    \begin{macrocode}
+\def\exf at csdo#1#2{\expandafter#1\csname#2\endcsname}
+\def\exf at csdotwo#1#2#3{\exf at exptwo#1#2\csname#3\endcsname}
+%    \end{macrocode}
+
+% \macro{\exf at append@def}
+% \macro{\exf at prepend@def}
+% Add definitions to macros (after or before original content):
+%    \begin{macrocode}
+\long\def\exf at append@def#1#2{\exf at exptwo\def#1\expandafter{#1#2}}
+\long\def\exf at prepend@switch#1#2#3{#2{#3#1}}
+\long\def\exf at prepend@def#1#2{\exf at exptwo\exf at prepend@switch{#1}{\def#1}{#2}}
+%    \end{macrocode}
+
+% \macro{\exf at expsetkeys}
+% A version of |\setkeys| from \textsf{xkeyval} which expands first:
+%    \begin{macrocode}
+\newcommand{\exf at expsetkeys}[2]{\edef\exf at tmp{#2}%
+  \exf at exparg{\setkeys{#1}}{\exf at tmp}}
+%    \end{macrocode}
+
+% \macro{\exf at href}
+% Display text with hyperreference passed by macro |#1|
+% (in case \textsf{hyperref} is loaded
+% and the reference is defined and not empty):
+%    \begin{macrocode}
+\newcommand{\exf at href}[2]{%
+  \ifdefined#1\ifx#1\exf at empty#2\else%
+   \ifdefined\hyperlink\protect\hyperlink{#1}{#2}\else#2\fi\fi\else#2\fi}
+%    \end{macrocode}
+
+% \macro{\exf at text}
+% \macro{\exf at ensuretext}
+% Two macros to display text in math mode.
+% |exf at text| is a wrapper for |\text| of \textsf{amstext}
+% in case the latter package is loaded.
+% |exf at ensuretext| makes sure the text is set in text mode
+% or within an |\mbox| in math math:
+%    \begin{macrocode}
+\newcommand{\exf at text}[1]{\ifdefined\text\text{#1}\else#1\fi}
+\newcommand{\exf at ensuretext}[1]{\ifmmode\mbox{#1}\else#1\fi}
+%    \end{macrocode}
+
+% \macro{\exf at addcontentsline}
+% Add a line to the table of contents unless macro in argument |#1| is empty:
+%    \begin{macrocode}
+\newcommand{\exf at addcontentsline}[2]{%
+  \ifx#1\exf at empty\else\addcontentsline{toc}{#1}{#2}\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Package Setup}
+% \label{sec:imp-setup}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Initialisation Options.}
+%
+% \macro{exframe.sty}
+% Some setup options are available while loading the package only.
+%
+% Configure names of main environments and counters:
+%    \begin{macrocode}
+\def\exf at problemname{problem}
+\def\exf at subproblemname{sub\exf at problemname}
+\def\exf at solutionname{solution}
+\def\exf at sheetname{sheet}
+\def\exf at problemcounter{problem}
+\def\exf at subproblemcounter{sub\exf at problemcounter}
+\def\exf at solutioncounter{solution}
+\def\exf at sheetcounter{sheet}
+\define at key{exframe.sty}{problemenv}{\def\exf at problemname{#1}}
+\define at key{exframe.sty}{subproblemenv}{\def\exf at subproblemname{#1}}
+\define at key{exframe.sty}{solutionenv}{\def\exf at solutionname{#1}}
+\define at key{exframe.sty}{sheetenv}{\def\exf at sheetname{#1}}
+\define at key{exframe.sty}{problemcounter}{\def\exf at problemcounter{#1}}
+\define at key{exframe.sty}{subproblemcounter}{\def\exf at subproblemcounter{#1}}
+\define at key{exframe.sty}{solutioncounter}{\def\exf at solutioncounter{#1}}
+\define at key{exframe.sty}{sheetcounter}{\def\exf at sheetcounter{#1}}
+%    \end{macrocode}
+
+% Whether to provide some extended configuration options
+% (available while loading only):
+%    \begin{macrocode}
+\define at boolkey{exframe.sty}[exf@]{extdata}[true]{}
+\define at boolkey{exframe.sty}[exf@]{extstyle}[true]{}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Setup Options.}
+%
+% \macro{exf at setup}
+% All remaining setup options are available
+% also when the package is already loaded.
+%
+% Main switch for solutions:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[]{solutions}[true]{}
+%    \end{macrocode}
+% Switch for writing pdf metadata:
+%    \begin{macrocode}
+\define at choicekey{exf at setup}{pdfdata}%
+  {auto,manual,sheet,off}[auto]{\def\exf at metadata{#1}}
+\def\exf at metadata{auto}
+%    \end{macrocode}
+% Write line number indicators to output file:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[exf@]{lineno}[true]{}
+%    \end{macrocode}
+% Prepare two-sided sheets:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[exf@]{twoside}[true]{}
+%    \end{macrocode}
+% Generate hyperreferences from solutions to corresponding problems:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[exf@]{solutionhref}[true]{}
+\exf at solutionhreftrue
+%    \end{macrocode}
+% Automatically generate labels for sheets and problems:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[exf@]{autolabelsheet}[true]{}
+\define at boolkey{exf at setup}[exf@]{autolabelproblem}[true]{}
+%    \end{macrocode}
+% Write warning message to document for better detection of inconsistencies:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[exf@]{warntext}[true]{}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Processing.}
+%
+% Process global options while loading package:
+%    \begin{macrocode}
+\ProcessOptionsX<exframe.sty,exf at setup>
+%    \end{macrocode}
+
+% \macro{\exercisesetup}
+% Configure package when package is already loaded:
+%    \begin{macrocode}
+\newcommand{\exercisesetup}[1]{\exf at expsetkeys{exf at setup}{#1}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Configuration}
+% \label{sec:imp-config}
+%
+% This section defines and describes the various configuration options
+% provided by the package. It also serves as a manual,
+% and most code can be recycled and adjusted for individual configurations:
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Definitions.}
+%
+% \macro{\exerciseconfig}
+% Set a configuration macro;
+% store definition in |exf at config@#2|;
+% use |\newcommand| for macros with arguments,
+% but (non-long) |\def| for plain definitions:
+%    \begin{macrocode}
+\newcommand{\exerciseconfig}[1]{%
+  \@ifnextchar[{\exf at configopt{#1}}{\exf at confignoopt{#1}}}
+\long\def\exf at configopt#1[#2]#3{%
+  \exf at csdo\def{exf at config@#1}{}%
+  \exf at csdo\renewcommand{exf at config@#1}[#2]{#3}}%
+\long\def\exf at confignoopt#1#2{\exf at csdo\def{exf at config@#1}{#2}}
+%    \end{macrocode}
+% \macro{\exerciseconfigappend}
+% \macro{\exerciseconfigprepend}
+% Append to a (parameterless) configuration macro:
+%    \begin{macrocode}
+\newcommand{\exerciseconfigappend}[2]{%
+  \exf at csdo\exf at append@def{exf at config@#1}{#2}}
+\newcommand{\exerciseconfigprepend}[2]{%
+  \exf at csdo\exf at prepend@def{exf at config@#1}{#2}}
+%    \end{macrocode}
+% \macro{\getexerciseconfig}
+% Get configuration macro:
+%    \begin{macrocode}
+\newcommand{\getexerciseconfig}[1]{\csname exf at config@#1\endcsname}
+%    \end{macrocode}
+% \macro{\exerciseconfigempty}
+% Test whether configuration macro |#1| is empty;
+% execute |#2| if empty, otherwise execute |#3|:
+%    \begin{macrocode}
+\newcommand{\exerciseconfigempty}[3]{\exf at csdo\ifx{exf at config@#1}\exf at empty%
+  #2\else#3\fi}
+%    \end{macrocode}
+
+% \macro{\exerciseifemtpy}
+% \macro{\exerciseifnotempty}
+% Code to test whether |#1| (expanded) is empty;
+% execute |#2| if empty, otherwise execute |#3|:
+%    \begin{macrocode}
+\long\def\exerciseifempty#1#2#3{\if&#1&#2\else#3\fi}
+\long\def\exerciseifnotempty#1#2{\if&#1&\else#2\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Terms.}
+%
+% \macro{term...}
+% Terms for sheet, problem, solution and points
+% (for adjustment or internationalisation):
+%    \begin{macrocode}
+\exerciseconfig{termsheet}{Sheet}
+\exerciseconfig{termsheets}{Sheets}
+\exerciseconfig{termproblem}{Problem}
+\exerciseconfig{termproblems}{Problems}
+\exerciseconfig{termsolution}{Solution}
+\exerciseconfig{termsolutions}{Solutions}
+\exerciseconfig{termpoint}{point}
+\exerciseconfig{termpoints}{points}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Formatting Styles.}
+%
+% \macro{style...}
+% Formatting styles to be applied for various parts of text.
+% Different styles will be applied in sequence from more general
+% to more specific.
+%
+% Basic style for all exercise text:
+%    \begin{macrocode}
+\exerciseconfig{styletext}{\normalfont}
+%    \end{macrocode}
+% Style for problems:
+%    \begin{macrocode}
+\exerciseconfig{styletextproblem}{}
+%    \end{macrocode}
+% Style for solutions:
+%    \begin{macrocode}
+\exerciseconfig{styletextsolution}{\footnotesize}
+%    \end{macrocode}
+% Basic style for titles:
+%    \begin{macrocode}
+\exerciseconfig{styletitle}{\bfseries}
+%    \end{macrocode}
+% Style for problem titles:
+%    \begin{macrocode}
+\exerciseconfig{styletitleproblem}{\large}
+%    \end{macrocode}
+% Style for subproblem titles:
+%    \begin{macrocode}
+\exerciseconfig{styletitlesubproblem}{}
+%    \end{macrocode}
+% Style for solution titles:
+%    \begin{macrocode}
+\exerciseconfig{styletitlesolution}{}
+%    \end{macrocode}
+% Style for problem section title in solution block:
+%    \begin{macrocode}
+\exerciseconfig{styletitlesolutionsproblem}{\small}
+%    \end{macrocode}
+% Style for solution block title:
+%    \begin{macrocode}
+\exerciseconfig{styletitlesolutions}{\normalsize}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Spacing.}
+%
+% \macro{skip...}
+% Spaces related to various elements.
+% Vertical space is typically combined with space declared elsewhere
+% using |\addvspace|.
+%
+% Space above problem environment:
+%    \begin{macrocode}
+\exerciseconfig{skipproblemabove}{3.25ex plus 1ex minus 1.5ex}
+%    \end{macrocode}
+% Space below problem environment:
+%    \begin{macrocode}
+\exerciseconfig{skipproblembelow}{3pt plus 1pt minus 1pt}
+%    \end{macrocode}
+% Space below or after problem title;
+% positive numbers generate vertical space
+% (problem body is started in new paragraph),
+% negative numbers generate horizontal space
+% (problem body continues on opening line):
+%    \begin{macrocode}
+\exerciseconfig{skipproblemtitle}{3pt plus 1pt minus 1pt}
+%    \end{macrocode}
+% Horizontal space between items in the problem opening line:
+%    \begin{macrocode}
+\exerciseconfig{skipprobleminfo}{0.5em}
+%    \end{macrocode}
+% Space for problem item and indentation;
+% |0pt| means no indentation and direct display of title;
+% positive numbers define an absolute amount;
+% |-1pt| (or any negative number) computes the amount of indentation
+% from the width of (standard) item plus separator:
+%    \begin{macrocode}
+\exerciseconfig{skipproblemitem}{0pt}
+%    \end{macrocode}
+
+% Spaces related to subproblem environment;
+% analogous to spaces related to problem environment,
+% see above:
+%    \begin{macrocode}
+\exerciseconfig{skipsubproblemabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsubproblembelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsubproblemtitle}{-1em}
+\exerciseconfig{skipsubprobleminfo}{0.25em}
+\exerciseconfig{skipsubproblemitem}{-1pt}
+%    \end{macrocode}
+
+% Spaces related to solution environment;
+% analogous to spaces related to problem environment,
+%    \begin{macrocode}
+\exerciseconfig{skipsolutionabove}{0ex}
+\exerciseconfig{skipsolutionbelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsolutiontitle}{-0.5em}
+\exerciseconfig{skipsolutioninfo}{0.25em}
+%    \end{macrocode}
+% |skipsolutionitem| and |skipsolutionitemsub|
+% are analogous to |skipproblemitem| described above;
+% they apply to solutions corresponding to problems and subproblems,
+% respectively:
+%    \begin{macrocode}
+\exerciseconfig{skipsolutionitem}{0pt}
+\exerciseconfig{skipsolutionitemsub}{0pt}
+%    \end{macrocode}
+
+% Spaces related to blocks of solutions;
+% space above and below a solution block:
+%    \begin{macrocode}
+\exerciseconfig{skipsolutionsabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsolutionsbelow}{1.5ex plus 0.5ex minus 1ex}
+%    \end{macrocode}
+% Space following problem titles in a solution block:
+%    \begin{macrocode}
+\exerciseconfig{skipsolutionsproblem}{1.0ex plus 0ex minus 0.5ex}
+%    \end{macrocode}
+% Space following title of a solution block:
+%    \begin{macrocode}
+\exerciseconfig{skipsolutionstitle}{1.0ex plus 0ex minus 0.5ex}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Hook Code.}
+%
+% \macro{insert...}
+% Code to process data and to insert text at various points of processing.
+%
+% Code to generate the title for a sheet;
+% minimalistic default to display the sheet title:
+%    \begin{macrocode}
+\exerciseconfig{insertsheettitle}{\centerline{\getsheetdata{title}}}
+%    \end{macrocode}
+% Code to clear the page at the start and at the end of a new sheet:
+%    \begin{macrocode}
+\exerciseconfig{insertsheetclearpage}{\exercisecleardoublepage}
+%    \end{macrocode}
+% Code to insert before a sheet is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertsheetbefore}{}
+%    \end{macrocode}
+% Code to insert after a sheet is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertsheetafter}{}
+%    \end{macrocode}
+% Code to insert before a solution block is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertsolutionsbefore}{}
+%    \end{macrocode}
+% Code to insert after a solution block is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertsolutionsafter}{}
+%    \end{macrocode}
+% Code to insert before a problem is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertproblembefore}{}
+%    \end{macrocode}
+% Code to insert after a problem is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertproblemafter}{}
+%    \end{macrocode}
+% Code to insert text into the problem opening line
+% by means of |\addprobleminfo|:
+%    \begin{macrocode}
+\exerciseconfig{insertprobleminfo}{}
+%    \end{macrocode}
+% Analogous definitions for subproblems:
+%    \begin{macrocode}
+\exerciseconfig{insertsubproblembefore}{}
+\exerciseconfig{insertsubproblemafter}{}
+\exerciseconfig{insertsubprobleminfo}{}
+%    \end{macrocode}
+% Analogous definitions for solutions:
+%    \begin{macrocode}
+\exerciseconfig{insertsolutionbefore}{}
+\exerciseconfig{insertsolutionafter}{}
+\exerciseconfig{insertsolutioninfo}{}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Text Composition for Environments.}
+%
+% \macro{compose...}
+% Macros to generate text for various situations.
+% Preferably the output is plain text without formatting,
+% but in some situations it may be required to
+% address formatting in these macros.
+%
+% Default separator for items:
+%    \begin{macrocode}
+\exerciseconfig{composeitemsep}{\ }
+%    \end{macrocode}
+% Compose sheet title;
+% arguments are sheet number and raw title (empty if not specified);
+% default is ``Sheet |#1|'' or given title ``|#2|'':
+%    \begin{macrocode}
+\exerciseconfig{composetitlesheet}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
+%    \end{macrocode}
+% Compose sheet title for pdf metadata;
+% arguments are sheet number and raw title:
+%    \begin{macrocode}
+\exerciseconfig{composemetasheet}[2]%
+  {\getexerciseconfig{composetitlesheet}{#1}{#2}}
+%    \end{macrocode}
+% Compose sheet title for table of contents;
+% arguments are sheet number and raw title:
+%    \begin{macrocode}
+\exerciseconfig{composetocsheet}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#1. #2}}
+%    \end{macrocode}
+% Compose problem item; argument is problem number:
+%    \begin{macrocode}
+\exerciseconfig{composeitemproblem}[1]{#1.}
+%    \end{macrocode}
+% Problem item separator:
+%    \begin{macrocode}
+\exerciseconfig{composeitemproblemsep}%
+  {\getexerciseconfig{composeitemsep}}
+%    \end{macrocode}
+% Compose problem title;
+% arguments are problem number (empty if item is split off)
+% and raw title (empty if not specified);
+% default is ``Problem |#1|.'' or ``|#1|. |#2|'':
+%    \begin{macrocode}
+\exerciseconfig{composetitleproblem}[2]{\exerciseifempty{#1}%
+   {\exerciseifempty{#2}{}{#2}}%
+   {\exerciseifempty{#2}{\getexerciseconfig{termproblem}\ %
+     \getexerciseconfig{composeitemproblem}{#1}}%
+    {\getexerciseconfig{composeitemproblem}{#1} #2}}}
+%    \end{macrocode}
+% Compose problem title for table of contents;
+% arguments are problem number and raw title:
+%    \begin{macrocode}
+\exerciseconfig{composetocproblem}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termproblem} #1}{#1. #2}}
+%    \end{macrocode}
+% Compose subproblem item; argument is subproblem number:
+%    \begin{macrocode}
+\exerciseconfig{composeitemsubproblem}[1]{#1}
+%    \end{macrocode}
+% Subproblem item separator:
+%    \begin{macrocode}
+\exerciseconfig{composeitemsubproblemsep}%
+  {\getexerciseconfig{composeitemsep}}
+%    \end{macrocode}
+% Compose subproblem title;
+% argument is subproblem number:
+%    \begin{macrocode}
+\exerciseconfig{composetitlesubproblem}[1]{#1}
+%    \end{macrocode}
+% Compose solution item; argument is problem or subproblem number:
+%    \begin{macrocode}
+\exerciseconfig{composeitemsolution}[2]{#1.}
+\exerciseconfig{composeitemsolutionsub}[2]{#2}
+%    \end{macrocode}
+% Solution item separator:
+%    \begin{macrocode}
+\exerciseconfig{composeitemsolutionsep}%
+  {\getexerciseconfig{composeitemsep}}
+%    \end{macrocode}
+% Compose title for single solution;
+% arguments are corresponding problem and subproblem number:
+%    \begin{macrocode}
+\exerciseconfig{composetitlesolutionsingle}[2]%
+  {\getexerciseconfig{termsolution}:}
+%    \end{macrocode}
+% Compose title for one out of several solutions;
+% arguments are corresponding problem and subproblem number:
+%    \begin{macrocode}
+\exerciseconfig{composetitlesolutionmulti}[2]{#2}
+%    \end{macrocode}
+% Compose table of contents line for solution;
+% arguments are problem number and raw title:
+%    \begin{macrocode}
+\exerciseconfig{composetocsolution}[2]%
+  {\getexerciseconfig{composetocproblem}{#1}{#2}}
+%    \end{macrocode}
+% Compose title for solution block:
+%    \begin{macrocode}
+\exerciseconfig{composetitlesolutions}%
+  {\getexerciseconfig{termsolutions}}
+%    \end{macrocode}
+% Compose table of contents line for solution block:
+%    \begin{macrocode}
+\exerciseconfig{composetocsolutions}%
+  {\getexerciseconfig{composetitlesolutions}}
+%    \end{macrocode}
+% Compose sectional title for solution following a single problem;
+% arguments are problem number and raw title:
+%    \begin{macrocode}
+\exerciseconfig{composetitlesolutionsproblemsingle}[2]%
+  {\getexerciseconfig{termsolution}}
+%    \end{macrocode}
+% Compose sectional title for solution of one problem within a block;
+% arguments are problem number and raw title:
+%    \begin{macrocode}
+\exerciseconfig{composetitlesolutionsproblemmulti}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termproblem} #1}{#1. #2}}
+%    \end{macrocode}
+% Compose label:
+%    \begin{macrocode}
+\exerciseconfig{composeitemsolution}[2]{#1#2}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Points.}
+%
+% Compose number of points:
+%    \begin{macrocode}
+\exerciseconfig{composepointsnum}[1]{#1}
+%    \end{macrocode}
+% Compose number of points followed by `points';
+% use singular `point' for $1$:
+%    \begin{macrocode}
+\exerciseconfig{composepoints}[1]{\getexerciseconfig{composepointsnum}{#1}~%
+  \ifdim #1pt=1pt\getexerciseconfig{termpoint}%
+  \else\getexerciseconfig{termpoints}\fi}
+%    \end{macrocode}
+% Compose points declaration for use in opening line:
+%    \begin{macrocode}
+\exerciseconfig{composepointsstart}[1]{(\getexerciseconfig{composepoints}{#1})}
+%    \end{macrocode}
+% Compose points declaration for use in margin:
+%    \begin{macrocode}
+\exerciseconfig{composepointsmargin}[1]{\getexerciseconfig{composepoints}{#1}}
+%    \end{macrocode}
+% Compose points declaration for use in text:
+%    \begin{macrocode}
+\exerciseconfig{composepointsbody}[1]{(\getexerciseconfig{composepoints}{#1})}
+%    \end{macrocode}
+% Compose points declaration for use in sheet data:
+%    \begin{macrocode}
+\exerciseconfig{composepointssheet}[1]{%
+  \exerciseifnotempty{#1}{\getexerciseconfig{composepoints}{#1}}}
+%    \end{macrocode}
+% Compose points declaration for solution with comment:
+%    \begin{macrocode}
+\exerciseconfig{composepointsaward}[2]%
+  {(\getexerciseconfig{composepoints}{#1}\exerciseifnotempty{#2}{; #2})}
+%    \end{macrocode}
+% Compose alternative points for solution declaration with comment:
+%    \begin{macrocode}
+\exerciseconfig{composepointsawardalt}[2]%
+  {(\getexerciseconfig{composepoints}{#1}*\exerciseifnotempty{#2}{; #2})}
+%    \end{macrocode}
+
+% Display points in the margin:
+%    \begin{macrocode}
+\exerciseconfig{insertpointsmargin}[1]{\marginpar{\footnotesize #1}}
+%    \end{macrocode}
+
+% Display warning about points mismatch:
+%    \begin{macrocode}
+\exerciseconfig{insertwarnpoints}[3]
+  {\textbf{points mismatch for #1 (#2 determined vs.\ #3 given)}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Counters.}
+%
+% Define counter display via configuration interface:
+%    \begin{macrocode}
+\exerciseconfig{countersheet}{\arabic{\exf at sheetcounter}}
+\exerciseconfig{counterproblem}{\arabic{\exf at problemcounter}}
+\exerciseconfig{counterproblemmax}{10}
+\exerciseconfig{countersubproblem}{\alph{\exf at subproblemcounter})}
+\exerciseconfig{countersubproblemmax}{m)}
+\exerciseconfig{countersheetequation}{\arabic{equation}}
+\exerciseconfig{counterproblemequation}{P\arabic{equation}}
+\exerciseconfig{countersolutionequation}{S\arabic{equation}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Further Definitions.}
+%
+% \macro{label...}
+% Templates for automatic generation of labels from tags:
+%    \begin{macrocode}
+\exerciseconfig{labelsheet}[1]{sheet:#1}
+\exerciseconfig{labelproblem}[1]{prob:#1}
+%    \end{macrocode}
+
+% \macro{toclevel...}
+% Table of contents levels for sheets, problems,
+% solutions of problems and solution blocks;
+% empty means no writing to table of contents:
+%    \begin{macrocode}
+\exerciseconfig{toclevelsheet}{}
+\exerciseconfig{toclevelproblem}{}
+\exerciseconfig{toclevelsolution}{}
+\exerciseconfig{toclevelsolutions}{}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Styles}
+% \label{sec:imp-styles}
+%
+% Styles are meant as a way to adjust
+% several configuration options at the same time
+% to achieve a consistent layout in some regard.
+% Useful examples can be found among the
+% extended exercise styles.
+% They can serve a starting point for further
+% custom styles.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Exercise Styles Code.}
+%
+% \macro{\defexercisestylearg}
+% Define a style with an argument:
+%    \begin{macrocode}
+\newcommand{\defexercisestylearg}[3][]{%
+  \def\exf at tmp{#1}\ifx\exf at tmp\exf at empty%
+   \define at key{exf at style}{#2}{#3}\else%
+   \define at key{exf at style}{#2}[#1]{#3}\fi}
+%    \end{macrocode}
+% \macro{\defexercisestyle}
+% Define a style with a boolean argument;
+% execute code onlf if true:
+%    \begin{macrocode}
+\newcommand{\defexercisestyle}[2]{%
+  \exf at csdotwo\long\def{exf at style@code@#1}{#2}%
+  \exf at exparg{\define at boolkey{exf at style}[exf at style@]{#1}[true]}%
+   {\csname ifexf at style@#1\endcsname\csname exf at style@code@#1\endcsname\fi}}
+%    \end{macrocode}
+% \macro{\exercisestyle}
+% Process styles:
+%    \begin{macrocode}
+\newcommand{\exercisestyle}[1]{\exf at expsetkeys{exf at style}{#1}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Default Exercise Styles.}
+%
+% \macro{solutionbelow}
+% Choose location for solutions:
+%    \begin{macrocode}
+\def\exf at solutionbelow{subproblem}
+\define at choicekey{exf at style}{solutionbelow}%
+  {here,subproblem,problem,sheet,manual}{\def\exf at solutionbelow{#1}}
+%    \end{macrocode}
+% Conditionals to compare solution locations:
+%    \begin{macrocode}
+\newcommand{\exf at solbelowis}[2]%
+  {\def\exf at tmp{#1}\ifx\exf at solutionbelow\exf at tmp#2\fi}
+%    \end{macrocode}
+%
+% \macro{sheetequation}
+% \macro{problemequation}
+% \macro{solutionequation}
+% Use separate equation counters for sheets, problems and solutions:
+%    \begin{macrocode}
+\defexercisestyle{sheetequation}{}
+\defexercisestyle{problemequation}{}
+\defexercisestyle{solutionequation}{}
+\exf at style@solutionequationtrue
+%    \end{macrocode}
+%
+% \macro{pointsat}
+% \macro{subpointsat}
+% Choose where points of problems and subproblems are displayed:
+%    \begin{macrocode}
+\def\exf at pointsat{start}
+\define at choicekey{exf at style}{pointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at pointsat{#1}}
+\def\exf at subpointsat{end}
+\define at choicekey{exf at style}{subpointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at subpointsat{#1}}
+%    \end{macrocode}
+% Conditionals to compare point locations:
+%    \begin{macrocode}
+\newcommand{\exf at pointsatis}[2]%
+  {\def\exf at tmp{#1}\ifx\exf at pointsat\exf at tmp#2\fi}
+\newcommand{\exf at subpointsatis}[2]%
+  {\def\exf at tmp{#1}\ifx\exf at subpointsat\exf at tmp#2\fi}
+%    \end{macrocode}
+%
+% \macro{problemby}
+% \macro{equationby}
+% Declare problems or equations as subcounter of other counter:
+%    \begin{macrocode}
+\defexercisestylearg{problemby}{\exf at numberproblemwithin{#1}}
+\defexercisestylearg{equationby}{\exf at numberequationwithin{#1}}
+%    \end{macrocode}
+%
+% \macro{pagebysheet}
+% \macro{problembysheet}
+% \macro{equationbysheet}
+% Number pages, problems or equations by sheet:
+%    \begin{macrocode}
+\defexercisestyle{pagebysheet}{%
+  \def\thepage{\csname the\exf at sheetcounter\endcsname.\arabic{page}}%
+  \def\theHpage{\csname theH\exf at sheetcounter\endcsname.\arabic{page}}%
+  \exerciseconfigappend{insertsheetbefore}{\setcounter{page}{1}}}
+\defexercisestyle{problembysheet}%
+  {\exf at numberproblemwithin{\exf at sheetcounter}}
+\defexercisestyle{equationbysheet}%
+  {\exf at numberequationwithin{\exf at sheetcounter}}
+%    \end{macrocode}
+%
+% \macro{fracpoints}
+% Use vulgar fractions to display binary fractional points:
+%    \begin{macrocode}
+\defexercisestyle{fracpoints}%
+  {\exerciseconfig{composepointsnum}[1]{\exf at nicefrac{##1}}}
+%    \end{macrocode}
+%
+% \macro{twoside}
+% Use two-sided layout for sheets:
+%    \begin{macrocode}
+\defexercisestylearg[true]{twoside}{\exercisesetup{twoside={#1}}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Extended Exercise Styles.}
+%
+% Declare more specific styles:
+%    \begin{macrocode}
+\ifexf at extstyle
+%    \end{macrocode}
+%
+% \macro{contents}
+% Add sheets and problems to table of contents:
+%    \begin{macrocode}
+\defexercisestyle{contents}{%
+  \exerciseconfig{toclevelsheet}{section}%
+  \exerciseconfig{toclevelproblem}{subsection}}
+%    \end{macrocode}
+% \macro{solutionsf}
+% Use sans serif font for solutions:
+%    \begin{macrocode}
+\defexercisestyle{solutionsf}{%
+  \exerciseconfigappend{styletextsolution}{\sffamily\let\itshape\slshape}}
+%    \end{macrocode}
+% \macro{solutiondimproblem}
+% Dim problem text if solutions are displayed:
+%    \begin{macrocode}
+\defexercisestyle{solutiondimproblem}{%
+  \RequirePackage{color}%
+  \exerciseconfigappend{styletextsolution}{\color[gray]{0}}%
+  \exerciseconfigappend{styletextproblem}{\color[gray]{0.2}}}
+%    \end{macrocode}
+% \macro{solutionsep}
+% Separate solutions by horizontal lines:
+%    \begin{macrocode}
+\defexercisestyle{solutionsep}{%
+  \exerciseconfig{insertsolutionsbefore}{\hrule\nopagebreak[3]\vspace{0.5ex}}%
+  \exerciseconfig{insertsolutionsafter}{\nopagebreak[3]\vspace{1.0ex}\hrule}}
+%    \end{macrocode}
+% \macro{plainheader}
+% Declare a simple sheet header with some configurable options;
+% the configuration options |styleheader...| define font styles,
+% |skipheaderbelow| the space below the header and
+% |composeheaderbelow...| some auxiliary text to be displayed
+% on the line below the header:
+%    \begin{macrocode}
+\defexercisestyle{plainheader}{%
+  \exerciseconfig{styleheadertitle}{\Large\bfseries}%
+  \exerciseconfig{styleheadercourse}{\sffamily}%
+  \exerciseconfig{styleheaderbelow}{\footnotesize}%
+  \exerciseconfig{skipheaderbelow}{3ex}%
+  \exerciseconfig{composeheaderbelowleft}{}%
+  \exerciseconfig{composeheaderbelowright}{}%
+  \exerciseconfig{composeheaderbelowcenter}{}%
+  \exerciseconfig{insertsheettitle}{\noindent%
+   \begin{minipage}{\textwidth}%
+   {\getexerciseconfig{styleheadertitle}%
+    \makebox[0pt][l]{\getexercisedata{course}}%
+    \hfill\makebox[0pt][r]{\getsheetdata{title}}\par}%
+   {\getexerciseconfig{styleheadercourse}%
+    \makebox[0pt][l]{\getexercisedata{institution}%
+     \exercisedataempty{period}{}{, \getexercisedata{period}}}%
+    \hfill\makebox[0pt][r]{\getexercisedata{instructor}}%
+    \vphantom{g}\par}%
+   \hrule%
+   {\def\tmp{}%
+    \exerciseconfigempty{composeheaderbelowleft}{}{\def\tmp{.}}%
+    \exerciseconfigempty{composeheaderbelowcenter}{}{\def\tmp{.}}%
+    \exerciseconfigempty{composeheaderbelowright}{}{\def\tmp{.}}%
+    \exerciseifnotempty{\tmp}%
+     {\getexerciseconfig{styleheaderbelow}\vphantom{\^A}%
+      \makebox[0pt][l]{\getexerciseconfig{composeheaderbelowleft}}%
+      \hfill\makebox[0pt][c]{\getexerciseconfig{composeheaderbelowcenter}}%
+      \hfill\makebox[0pt][r]{\getexerciseconfig{composeheaderbelowright}}%
+      \vspace*{-\baselineskip}\vspace*{-\parskip}\par}}%
+   \end{minipage}%
+   \par\addvspace{\getexerciseconfig{skipheaderbelow}}}}
+%    \end{macrocode}
+%
+% Done with extended styles:
+%    \begin{macrocode}
+\fi
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Metadata}
+% \label{sec:imp-metadata}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Global Metadata Code.}
+%
+% \macro{\defexercisedata}
+% Declare global metadata field
+% by defining a key \textit{key} in category |exf at data|
+% that stores the chosen value in |\exf at data@|\textit{key}:
+%    \begin{macrocode}
+\newcommand{\defexercisedata}[1]{%
+  \exf at csdo\def{exf at data@#1}{}%
+  \define at key{exf at data}{#1}%
+   {\exf at csdo\gdef{exf at data@#1}{##1}}}
+%    \end{macrocode}
+% \macro{\exercisedata}
+% Process key-value pairs:
+%    \begin{macrocode}
+\newcommand{\exercisedata}[1]{\setkeys{exf at data}{#1}}
+%    \end{macrocode}
+% \macro{\getexercisedata}
+% Read global metadata:
+%    \begin{macrocode}
+\newcommand{\getexercisedata}[1]{\csname exf at data@#1\endcsname}
+%    \end{macrocode}
+% \macro{\exercisedataempty}
+% Check whether the field is empty:
+%    \begin{macrocode}
+\newcommand{\exercisedataempty}[3]{\exf at csdo\ifx{exf at data@#1}\exf at empty%
+  #2\else#3\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Global Metadata Declarations.}
+%
+% Declare fields corresponding to standard pdf metadata:
+%    \begin{macrocode}
+\defexercisedata{author}
+\defexercisedata{title}
+\defexercisedata{subject}
+\defexercisedata{keyword}
+%    \end{macrocode}
+% Declare additional general purpose fields:
+%    \begin{macrocode}
+\defexercisedata{date}
+%    \end{macrocode}
+% Declare metadata related to courses:
+%    \begin{macrocode}
+\defexercisedata{instructor}
+\defexercisedata{course}
+\defexercisedata{institution}
+\defexercisedata{period}
+\defexercisedata{material}
+%    \end{macrocode}
+% Overwrite standard definitions for |author|, |title|, |date|
+% to also fill ordinary \LaTeX{} structures:
+%    \begin{macrocode}
+\define at key{exf at data}{author}{\gdef\exf at data@author{#1}\author{#1}}
+\define at key{exf at data}{title}{\gdef\exf at data@title{#1}\title{#1}}
+\define at key{exf at data}{date}{\gdef\exf at data@date{#1}\date{#1}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheet Metadata.}
+%
+% \macro{\defsheetdata}
+% Declare sheet metadata field
+% by defining a key \textit{key} in category |exf at sheet|
+% that stores the chosen value in |\exf at data@sheet@|\textit{key}:
+%    \begin{macrocode}
+\newcommand{\defsheetdata}[1]{%
+  \exf at csdo\def{exf at data@sheet@#1}{}%
+  \define at key{exf at sheet}{#1}%
+   {\exf at csdo\def{exf at data@sheet@#1}{##1}}}
+%    \end{macrocode}
+% \macro{\getsheetdata}
+% Read global metadata:
+%    \begin{macrocode}
+\newcommand{\getsheetdata}[1]{\csname exf at data@sheet@#1\endcsname}
+%    \end{macrocode}
+% \macro{\sheetdataempty}
+% Check whether the field is empty:
+%    \begin{macrocode}
+\newcommand{\sheetdataempty}[3]{\exf at csdo\ifx{exf at data@sheet@#1}\exf at empty%
+  #2\else#3\fi}
+%    \end{macrocode}
+
+% Declare general purpose fields:
+%    \begin{macrocode}
+\defsheetdata{due}
+\defsheetdata{handout}
+\defsheetdata{editdate}
+\defsheetdata{author}
+\defsheetdata{editor}
+%    \end{macrocode}
+
+% Special title processing:
+%    \begin{macrocode}
+\def\exf at data@sheet at rawtitle{}
+\define at key{exf at sheet}{title}{\def\exf at data@sheet at rawtitle{#1}}
+\def\exf at data@sheet at title{\exf at config@composetitlesheet%
+  {\csname the\exf at sheetcounter\endcsname}{\exf at data@sheet at rawtitle}}%
+%    \end{macrocode}
+% Special points processing:
+%    \begin{macrocode}
+\def\exf at data@sheet at rawpoints{}
+\def\exf at data@sheet at points{\exf at config@composepointssheet%
+  {\exf at data@sheet at rawpoints}}%
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Metadata.}
+%
+% \macro{\defproblemdata}
+% Declare sheet metadata field
+% by defining a key \textit{key} in category |exf at problem|
+% that stores the chosen value in |\exf at data@problem@|\textit{key}:
+%    \begin{macrocode}
+\newcommand{\defproblemdata}[1]{%
+  \exf at csdo\def{exf at data@problem@#1}{}%
+  \define at key{exf at problem}{#1}%
+   {\exf at csdo\def{exf at data@problem@#1}{##1}}}
+%    \end{macrocode}
+% \macro{\getproblemdata}
+% Read global metadata:
+%    \begin{macrocode}
+\newcommand{\getproblemdata}[1]{\csname exf at data@problem@#1\endcsname}
+%    \end{macrocode}
+% \macro{\problemdataempty}
+% Check whether the field is empty:
+%    \begin{macrocode}
+\newcommand{\problemdataempty}[3]{\exf at csdo\ifx{exf at data@problem@#1}\exf at empty%
+  #2\else#3\fi}
+%    \end{macrocode}
+
+% Special title processing:
+%    \begin{macrocode}
+\def\exf at data@problem at rawtitle{}
+\define at key{exf at problem}{title}{\def\exf at data@problem at rawtitle{#1}}
+\def\exf at data@problem at title{\exf at config@composetitleproblem{%
+ \csname the\exf at problemcounter\endcsname}{\exf at data@problem at rawtitle}}%
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Info Code.}
+%
+% \macro{\exf at section}
+% Write out problem opening line followed by some amount of skip
+% (positive dimensions add vertical space,
+% negative dimensions add horizontal space);
+% protected expand argument if in horizontal mode
+% (because it will be held until text is output
+% and some definitions may become invalid):
+%    \begin{macrocode}
+\newcommand{\exf at section}[2]{\setlength\exf at tmpdim{#1}%
+  \ifdim\exf at tmpdim<0pt%
+   \protected at edef\exf at tmp{#2}%
+  \else%
+   \def\exf at tmp{#2}%
+  \fi%
+  \exf at exparg{\@startsection{}{}{0pt}{0pt}{#1}{}*}{\exf at tmp}}
+%    \end{macrocode}
+
+% \macro{\exf at init@intro}
+% Clean info buffer, define amount of skip between items:
+%    \begin{macrocode}
+\newcommand{\exf at init@intro}[1]%
+  {\def\exf at intro{}\def\exf at introitem{}\def\exf at intro@skip{#1}}
+%    \end{macrocode}
+% \macro{\exf at append@intro}
+% Append to info buffer:
+%    \begin{macrocode}
+\newcommand{\exf at append@intro}[1]%
+  {\exf at append@def\exf at intro{#1\hspace{\exf at intro@skip}}}
+%    \end{macrocode}
+% \macro{\exf at prepend@intro}
+% Prepend to info buffer:
+%    \begin{macrocode}
+\newcommand{\exf at prepend@intro}[1]%
+  {\exf at prepend@def\exf at intro{#1\hspace{\exf at intro@skip}}}
+%    \end{macrocode}
+% \macro{\exf at write@intro}
+% Compose opening line:
+%    \begin{macrocode}
+\newcommand{\exf at write@intro}[1]{%
+  \ifx\exf at intro\exf at empty%
+   \exf at section{0pt}{\exf at introitem}%
+  \else%
+   \exf at section{#1}{\exf at introitem\exf at intro\unskip}%
+  \fi}%
+%    \end{macrocode}
+
+% \macro{\addprobleminfo}
+% Interface to append or prepend to info buffer:
+%    \begin{macrocode}
+\newcommand{\addprobleminfo}{\@ifstar\exf at prepend@intro\exf at append@intro}
+%    \end{macrocode}
+
+% \macro{\exf at addinfoswitch}
+% Add a switch for displaying problem info:
+%    \begin{macrocode}
+\newcommand{\exf at addinfoswitch}[1]%
+  {\define at boolkey{exf at infoswitch}[exf at showdata@]{#1}[true]{}}
+%    \end{macrocode}
+% \macro{\defprobleminfo}
+% Declare a problem info field,
+% add corresponding info switch,
+% process key-value pair if switch activated:
+%    \begin{macrocode}
+\newcommand{\defprobleminfo}[2]{%
+  \exf at addinfoswitch{#1}%
+  \exerciseconfig{compose at probleminfo@#1}[1]{#2}%
+  \exf at exparg{\define at key{exf at probleminfo}{#1}}%
+   {\csname ifexf at showdata@#1\endcsname\exf at append@intro{%
+    \csname exf at config@compose at probleminfo@#1\endcsname{##1}}\fi}}
+%    \end{macrocode}
+% \macro{\showprobleminfo}
+% Process info switches, expand argument first:
+%    \begin{macrocode}
+\newcommand{\showprobleminfo}[1]{\exf at expsetkeys{exf at infoswitch}{#1}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Info Declarations.}
+%
+% Declare general purpose fields:
+%    \begin{macrocode}
+\defprobleminfo{optional}{\emph{#1:}}
+\showprobleminfo{optional}
+\defprobleminfo{difficulty}{(#1)}
+%    \end{macrocode}
+
+% Declare fields for internal information (mostly):
+%    \begin{macrocode}
+\defprobleminfo{comment}{#1}
+\defprobleminfo{author}{$\langle$#1$\rangle$}
+\defprobleminfo{editor}{$\{$#1$\}$}
+\defprobleminfo{source}{[#1]}
+\defprobleminfo{keyword}{\#(#1)}
+%    \end{macrocode}
+
+% Declare more specific fields:
+%    \begin{macrocode}
+\ifexf at extdata
+\defprobleminfo{review}{#1}
+\defprobleminfo{recycle}{[[#1]]}
+\defprobleminfo{timesolve}{\{#1\}}
+\defprobleminfo{timepresent}{\{\!\{#1\}\!\}}
+\fi
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Write Metadata to PDF Files.}
+%
+% \macro{\exf at writemetadata}
+% Write Metadata to PDF Files in case \textsf{hyperref} is available,
+% choose between global and sheet version, pass through unfilled values:
+%    \begin{macrocode}
+\newcommand{\exf at writemetadata}[1]{%
+  \ifdefined\hypersetup%
+   \def\exf at tmp{#1}\ifx\exf at tmp\exf at empty%
+%    \end{macrocode}
+% Write global author and title:
+%    \begin{macrocode}
+    \ifx\exf at data@author\exf at empty\else%
+     \hypersetup{pdfauthor={\exf at data@author}}\fi%
+    \ifx\exf at data@title\exf at empty\else%
+     \hypersetup{pdftitle={\exf at data@title}}\fi%
+   \else%
+%    \end{macrocode}
+% Write sheet author (if available) and compose sheet title:
+%    \begin{macrocode}
+    \ifx\exf at data@sheet at author\exf at empty%
+     \ifx\exf at data@author\exf at empty\else%
+      \hypersetup{pdfauthor={\exf at data@author}}\fi%
+    \else\hypersetup{pdfauthor={\exf at data@sheet at author}}\fi%
+    \hypersetup{pdftitle={\exf at config@composemetasheet%
+     {\csname the\exf at sheetcounter\endcsname}{\exf at data@sheet at rawtitle}}}%
+   \fi%
+%    \end{macrocode}
+% Write subject and keywords:
+%    \begin{macrocode}
+   \ifx\exf at data@subject\exf at empty\else%
+    \hypersetup{pdfsubject={\exf at data@subject}}\fi%
+   \ifx\exf at data@keyword\exf at empty\else%
+    \hypersetup{pdfkeywords={\exf at data@keyword}}\fi%
+  \fi%
+%    \end{macrocode}
+% Do not write again:
+%    \begin{macrocode}
+  \gdef\exf at metadata{off}}
+%    \end{macrocode}
+
+% Automatic writing at |\begin{document}|:
+%    \begin{macrocode}
+\AtBeginDocument{\def\exf at tmp{auto}\ifx\exf at metadata\exf at tmp%
+  \exf at writemetadata{}\fi}
+%    \end{macrocode}
+
+% \macro{\writeexercisedata}
+% Write metadata manually:
+%    \begin{macrocode}
+\newcommand{\writeexercisedata}{\def\exf at tmp{manual}\ifx\exf at metadata\exf at tmp%
+  \exf at writemetadata{}\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Counters}
+% \label{sec:imp-counter}
+%
+% \macro{sheet}
+% \macro{problem}
+% \macro{subproblem}
+% \macro{solution}
+% Define main counters (with customised names if necessary)
+% and equation counters:
+%    \begin{macrocode}
+\newcounter{\exf at sheetcounter}
+\newcounter{\exf at problemcounter}
+\newcounter{\exf at subproblemcounter}[\exf at problemcounter]
+\newcounter{\exf at solutioncounter}[\exf at problemcounter]
+\newcount\exf at eqsav
+\newcounter{exf at sheetequation}
+\newcounter{exf at problemequation}
+\newcounter{exf at solutionequation}
+%    \end{macrocode}
+
+% Implement counter display;
+% take care of corresponding \textsf{hyperref} labels:
+%    \begin{macrocode}
+\exf at csdo\def{the\exf at sheetcounter}{\exf at config@countersheet}
+\exf at csdo\def{the\exf at problemcounter}{\exf at config@counterproblem}
+\exf at csdo\def{the\exf at subproblemcounter}{\exf at config@countersubproblem}
+\def\theexf at sheetequation{\exf at config@countersheetequation}
+\def\theHexf at sheetequation{sheet.\arabic{equation}}
+\def\theexf at problemequation{\exf at config@counterproblemequation}
+\def\theHexf at problemequation{prob.\arabic{equation}}
+\def\theexf at solutionequation{\exf at config@countersolutionequation}
+\def\theHexf at solutionequation{sol.\arabic{equation}}
+%    \end{macrocode}
+
+% \macro{\exf at numberproblemwithin}
+% Declare problem counter as subcounter of |#1|:
+%    \begin{macrocode}
+\newcommand{\exf at numberproblemwithin}[1]{%
+  \@addtoreset{\exf at problemcounter}{#1}%
+  \exf at csdo\def{the\exf at problemcounter}%
+   {\csname the#1\endcsname.\exf at config@counterproblem}}
+%    \end{macrocode}
+
+% \macro{\exf at numberequationwithin}
+% Declare various new equation counters as subcounter of |#1|;
+% take care of corresponding \textsf{hyperref} labels:
+%    \begin{macrocode}
+\newcommand{\exf at numberequationwithin}[1]{%
+  \@addtoreset{exf at sheetequation}{#1}%
+  \def\theexf at sheetequation%
+   {\csname the#1\endcsname.\exf at config@countersheetequation}%
+  \def\theHexf at sheetequation%
+   {\csname theH#1\endcsname.sheet.\arabic{equation}}%
+  \@addtoreset{exf at problemequation}{#1}%
+  \def\theexf at problemequation%
+   {\csname the#1\endcsname.\exf at config@counterproblemequation}%
+  \def\theHexf at problemequation%
+   {\csname theH#1\endcsname.prob.\arabic{equation}}%
+  \@addtoreset{exf at solutionequation}{#1}%
+  \def\theexf at solutionequation%
+   {\csname the#1\endcsname.\exf at config@countersolutionequation}%
+  \def\theHexf at solutionequation%
+   {\csname theH#1\endcsname.sol.\arabic{equation}}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Buffers}
+% \label{sec:imp-buffer}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{File Output.}
+%
+% \macro{\ifexf at infile}
+% Conditional whether an output file is presently in use:
+%    \begin{macrocode}
+\newif\ifexf at infile\exf at infilefalse
+%    \end{macrocode}
+% \macro{\exf at out}
+% Reserve file handle:
+%    \begin{macrocode}
+\newwrite\exf at out
+%    \end{macrocode}
+
+% \macro{\exf at writeline}
+% Write a line to the file:
+%    \begin{macrocode}
+\newcommand{\exf at writeline}[1]{\immediate\write\exf at out{#1}}
+%    \end{macrocode}
+
+% \macro{\exf at linesep}
+% Return a separator line:
+%    \begin{macrocode}
+\newcommand{\exf at linesep}%
+  {\@percentchar---------------------------------------}
+%    \end{macrocode}
+% \macro{\exf at lineno}
+% Return current position in source file;
+% display line number and source file name
+% (if available via package \textsf{currfile}):
+%    \begin{macrocode}
+\newcommand{\exf at lineno}{\@percentchar%
+  \ifdefined\currfilename\currfilename\space\fi%
+  l.\the\inputlineno}
+%    \end{macrocode}
+
+% \macro{\exf at startfile}
+% Open a new file |#1.sol| (do nothing if already open);
+% indicate source, switch to manual solution display mode:
+%    \begin{macrocode}
+\newcommand{\exf at startfile}[1]{%
+  \ifexf at infile\else%
+   \global\exf at infiletrue%
+   \gdef\exf at solutionbelow{manual}%
+   \edef\exf at tmp{#1}%
+   \immediate\openout\exf at out\exf at tmp.sol%
+   \exf at writeline{\@percentchar%
+    generated from file `\jobname' by exframe.sty}%
+   \ifexf at lineno\exf at writeline{\exf at lineno}\fi%
+   \exf at writeline{}%
+  \fi}
+%    \end{macrocode}
+
+% \macro{\exf at closefile}
+% Close file (if open);
+% indicate position, close and reset variables:
+%    \begin{macrocode}
+\newcommand{\exf at closefile}{%
+  \ifexf at infile%
+   \ifexf at lineno%
+    \exf at writeline{\exf at linesep}\exf at writeline{\exf at lineno}\fi%
+   \exf at writeline{\@backslashchar endinput}%
+   \immediate\closeout\exf at out%
+   \global\exf at infilefalse%
+  \fi}
+%    \end{macrocode}
+
+% Make sure to properly close file at the end:
+%    \begin{macrocode}
+\AtEndDocument{\exf at closefile}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solution Buffer.}
+%
+% \macro{\exf at buf}
+% \macro{\ifexf at bufclean}
+% Declare a token buffer for storing the solutions
+% and a conditional indicating whether the buffer has been used:
+%    \begin{macrocode}
+\newtoks\exf at buf
+\newif\ifexf at bufclean\exf at bufcleantrue
+%    \end{macrocode}
+
+% \macro{\exf at clearbuf}
+% Clear solution buffer and mark clean:
+%    \begin{macrocode}
+\def\exf at clearbuf{\global\exf at bufcleantrue\global\exf at buf={}}
+%    \end{macrocode}
+% \macro{\exf at append@buf}
+% Append tokens to buffer:
+%    \begin{macrocode}
+\def\exf at append@buf#1{\global\exf at buf=\expandafter{\the\exf at buf#1}}
+%    \end{macrocode}
+% \macro{\exf at addbufline}
+% Add a protected expanded line to the buffer:
+%    \begin{macrocode}
+\def\exf at addbufline#1{{\protected at edef\exf at tmp{#1}%
+  \exf at exptwo\exf at append@buf{\exf at tmp^^J}}}
+%    \end{macrocode}
+
+% \macro{\exf at sourcebuf}
+% Source the solution buffer into the document:
+%    \begin{macrocode}
+\def\exf at sourcebuf{\exf at exptwo\scantokens{\the\exf at buf}}
+%    \end{macrocode}
+% \macro{\exf at writebuf}
+% Write the buffer into the solution file:
+%    \begin{macrocode}
+\def\exf at writebuf{\exf at writeline{\the\exf at buf}}
+%    \end{macrocode}
+
+% \macro{\exf at verbatim}
+% Start reading the buffer from the environment body:
+%    \begin{macrocode}
+\newcommand{\exf at verbatim}{%
+  \begingroup%
+  \@bsphack%
+  \let\do\@makeother\dospecials%
+  \catcode`\^^M\active%
+  \def\verbatim at processline{\exf at exptwo\exf at append@buf{\the\verbatim at line^^J}}%
+  \verbatim at start}
+%    \end{macrocode}
+
+% \macro{\exf at endverbatim}
+% Stop reading the buffer:
+%    \begin{macrocode}
+\newcommand{\exf at endverbatim}{\@esphack\endgroup}
+%    \end{macrocode}
+
+% \macro{\exf at scanblock}
+% Scan an optional argument from a verbatim block;
+% allow for an empty block and an empty first line;
+% argument |#1| is macro to be called eventually:
+%    \begin{macrocode}
+\def\exf at scanblock#1{%
+%    \end{macrocode}
+% Check for empty first line:
+%    \begin{macrocode}
+  \@ifnextchar\par{\exf at scanblock@par{#1}}{\exf at scanblock@sel{#1}}}
+%    \end{macrocode}
+% Handle empty first line, implies no optional argument:
+%    \begin{macrocode}
+\long\def\exf at scanblock@par#1\par{\exf at scanblock@sel{#1}[]}
+%    \end{macrocode}
+% Check for optional argument (|[|) and for block ending (|\end|):
+%    \begin{macrocode}
+\def\exf at scanblock@sel#1{\@ifnextchar[{\exf at scanblock@opt{#1}}%
+  {\@ifnextchar\end{\exf at scanblock@end{#1}}{\exf at scanblock@noopt{#1}}}}
+%    \end{macrocode}
+% Handle empty block, hopefully environment matches (otherwise?!):
+%    \begin{macrocode}
+\def\exf at scanblock@end#1\end#2{%
+  \def\exf at tmp{#2}\ifx\exf at tmp\@currenvir%
+    \def\exf at verbatim{}\def\exf at endverbatim{}%
+  \fi%
+  #1{}{\scantokens{\end{#2}}}}
+%    \end{macrocode}
+% Pass on without and with optional argument;
+% pass on optional argument and any token scanned prematurely:
+%    \begin{macrocode}
+\def\exf at scanblock@noopt#1#2{#1{}{\scantokens#2}}
+\def\exf at scanblock@opt#1[#2]{#1{#2}{}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Points}
+% \label{sec:imp-points}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Binary Rational Numbers.}
+%
+% \macro{\exf at splitsign}
+% \macro{\exf at splitdecimal}
+% Split a decimal float number into sign, integer and fractional part:
+%    \begin{macrocode}
+\def\exf at splitsign#1-#2-#3&{\def\exf at splitnum{#1#2}\def\exf at splitminus{#3}}
+\def\exf at splitdecimal#1.#2.#3&{\def\exf at splitint{#1}\def\exf at splitdec{#2}}
+%    \end{macrocode}
+
+% \macro{\exf at nicefrac}
+% Display a float number as a fraction
+% with denominators 2, 4 or 8 when possible;
+% first split number, complete missing zeros and handle cases:
+%    \begin{macrocode}
+\newcommand{\exf at nicefrac}[1]{%
+  \edef\exf at tmp{#1}%
+  \expandafter\exf at splitsign\exf at tmp--&%
+  \expandafter\exf at splitdecimal\exf at splitnum..&%
+  \if&\exf at splitint&\def\exf at splitint{0}\fi%
+  \if&\exf at splitdec&\def\exf at splitdec{0}\fi%
+  \def\exf at tmp{\exf at splitint.\exf at splitdec}%
+  \ifnum\exf at splitdec=0\def\exf at tmp{\exf at splitint}\fi%
+  \ifnum\exf at splitdec=5\def\exf at tmp{\exf at intfrac{\exf at splitint}{1}{2}}\fi%
+  \ifnum\exf at splitdec=25\def\exf at tmp{\exf at intfrac{\exf at splitint}{1}{4}}\fi%
+  \ifnum\exf at splitdec=75\def\exf at tmp{\exf at intfrac{\exf at splitint}{3}{4}}\fi%
+  \ifnum\exf at splitdec=125\def\exf at tmp{\exf at intfrac{\exf at splitint}{1}{8}}\fi%
+  \ifnum\exf at splitdec=375\def\exf at tmp{\exf at intfrac{\exf at splitint}{3}{8}}\fi%
+  \ifnum\exf at splitdec=625\def\exf at tmp{\exf at intfrac{\exf at splitint}{5}{8}}\fi%
+  \ifnum\exf at splitdec=875\def\exf at tmp{\exf at intfrac{\exf at splitint}{7}{8}}\fi%
+  \ifx\exf at splitminus\exf at empty\else$\exf at splitminus$\fi\exf at tmp%
+}
+%    \end{macrocode}
+
+% \macro{\exf at intfrac}
+% Display a vulgar fraction
+% such as 12$^3\mskip-4mu/\mskip-2mu_4$:
+%    \begin{macrocode}
+\newcommand{\exf at intfrac}[3]{%
+  \ifnum#1=0\else#1\fi%
+  \ifnum#2=0\else$%
+   ^{\exf at text{#2}}%
+   \mskip-4mu/\mskip-2mu%
+   _{\exf at text{#3}}$\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheet Points Code.}
+%
+% \macro{\exf at sheet@points at dim}
+% Declare a metric register to sum overall points on a sheet;
+% equate unit |pt| to a point:
+%    \begin{macrocode}
+\newlength{\exf at sheet@points at dim}
+%    \end{macrocode}
+% \macro{\exf at notesheetpoints}
+% Store a sheet point number in a macro:
+%    \begin{macrocode}
+\newcommand{\exf at notesheetpoints}[2]{%
+  \exf at csdo\gdef{exf at sheetpoints@#1}{#2}}
+%    \end{macrocode}
+% Make sure the macros in code written to the |.aux| file exist:
+%    \begin{macrocode}
+\AtBeginDocument{\immediate\write\@auxout{%
+  \string\providecommand{\string\exf at notesheetpoints}[2]{}}}
+%    \end{macrocode}
+% \macro{\exf at writesheetpoints}
+% Write sheet points to the |.aux| file:
+%    \begin{macrocode}
+\newcommand{\exf at writesheetpoints}[1]%
+  {\immediate\write\@auxout{\string\exf at notesheetpoints{\sheettag}{#1}}}
+%    \end{macrocode}
+% \macro{\getsheetpoints}
+% Read sheet points stored in |.aux| file:
+%    \begin{macrocode}
+\newcommand{\getsheetpoints}[1]{\ifcsname exf at sheetpoints@#1\endcsname%
+  \csname exf at sheetpoints@#1\endcsname\else 0\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Points Code.}
+%
+% \macro{\exf at problem@points at dim}
+% Declare a metric register to sum overall points in a problem;
+% equate unit |pt| to a point:
+%    \begin{macrocode}
+\newlength{\exf at problem@points at dim}
+%    \end{macrocode}
+% \macro{\exf at noteproblempoints}
+% Store a problem point number in a macro:
+%    \begin{macrocode}
+\newcommand{\exf at noteproblempoints}[2]{%
+  \exf at csdo\gdef{exf at problempoints@#1}{#2}}
+%    \end{macrocode}
+% Make sure the macros written to the |.aux| file exist:
+%    \begin{macrocode}
+\AtBeginDocument{\immediate\write\@auxout{%
+  \string\providecommand{\string\exf at noteproblempoints}[2]{}}}
+%    \end{macrocode}
+% \macro{\exf at writeproblempoints}
+% Write problem points to the |.aux| file:
+%    \begin{macrocode}
+\newcommand{\exf at writeproblempoints}[1]%
+  {\immediate\write\@auxout{\string\exf at noteproblempoints{\problemtag}{#1}}}
+%    \end{macrocode}
+% \macro{\getproblempoints}
+% Read problem points stored in |.aux| file:
+%    \begin{macrocode}
+\newcommand{\getproblempoints}[1]{\ifcsname exf at problempoints@#1\endcsname%
+  \csname exf at problempoints@#1\endcsname\else 0\fi}
+%    \end{macrocode}
+
+% \macro{\showpoints}
+% Show points within a problem or subproblem:
+%    \begin{macrocode}
+\newcommand{\showpoints}{%
+  \ifdefined\exf at in@subproblem%
+   \ifdefined\exf at subproblem@points%
+    \exf at ensuretext{\exf at config@composepointsbody{\exf at subproblem@points}}%
+    \global\let\exf at subproblem@points\@undefined%
+   \fi%
+  \else\ifdefined\exf at in@problem%
+   \ifdefined\exf at problem@pointsshow%
+    \exf at ensuretext{\exf at config@composepointsbody{\exf at problem@pointsshow}}%
+    \global\let\exf at problem@pointsshow\@undefined%
+   \fi%
+  \fi\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solution Points Code.}
+%
+% \macro{\exf at solution@points at dim}
+% Declare a metric register to sum overall (mandatory) points in a solution;
+% equate unit |pt| to a point:
+%    \begin{macrocode}
+\newlength{\exf at solution@points at dim}
+%    \end{macrocode}
+
+% \macro{\exf at awardpointsalt}
+% Award points for alternative or optional solution;
+% does not count towards solution total:
+%    \begin{macrocode}
+\newcommand{\exf at awardpointsalt}[2][]{%
+  \exf at ensuretext{\exf at config@composepointsawardalt{#2}{#1}}}
+%    \end{macrocode}
+% \macro{\exf at awardpointsreg}
+% Award points for regular solution;
+% counts towards solution total:
+%    \begin{macrocode}
+\newcommand{\exf at awardpointsreg}[2][]{%
+  \global\addtolength{\exf at solution@points at dim}{#2 pt}%
+  \exf at ensuretext{\exf at config@composepointsaward{#2}{#1}}}
+%    \end{macrocode}
+% \macro{\awardpoints}
+% Award points within solution with optional starred form:
+%    \begin{macrocode}
+\newcommand{\awardpoints}{\@ifstar\exf at awardpointsalt\exf at awardpointsreg}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Environments}
+% \label{sec:imp-env}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheets.}
+%
+% \macro{exf at sheet}
+% Define options for |sheet| environment:
+%    \begin{macrocode}
+\define at key{exf at sheet}{points}{\def\exf at points@given{#1}}
+\define at key{exf at sheet}{number}{\setcounter{\exf at sheetcounter}{#1}}
+\define at key{exf at sheet}{label}{\def\exf at label{#1}}
+\define at key{exf at sheet}{tag}{\def\sheettag{#1}}
+%    \end{macrocode}
+
+% \macro{sheet}
+% Define |sheet| environment (potentially using custom name):
+%    \begin{macrocode}
+\newenvironment{\exf at sheetname}[1][]{%
+%    \end{macrocode}
+% Insert hook code to clear page, step counter:
+%    \begin{macrocode}
+  \exf at config@insertsheetclearpage%
+  \refstepcounter{\exf at sheetcounter}%
+%    \end{macrocode}
+% Use equation counter for sheets:
+%    \begin{macrocode}
+  \ifexf at style@sheetequation%
+   \exf at eqsav\value{equation}%
+   \setcounter{equation}{\value{exf at sheetequation}}%
+   \let\theequation\theexf at sheetequation%
+   \let\theHequation\theHexf at sheetequation%
+  \fi%
+%    \end{macrocode}
+% Reset optional arguments, process arguments:
+%    \begin{macrocode}
+  \let\exf at points@given\@undefined%
+  \def\sheettag{\csname the\exf at sheetcounter\endcsname}%
+  \setlength{\exf at sheet@points at dim}{0pt}%
+  \let\exf at label\@undefined%
+  \setkeys{exf at sheet}{#1}%
+%    \end{macrocode}
+% Process automatic and manual labels:
+%    \begin{macrocode}
+  \ifexf at autolabelsheet\label{\exf at config@labelsheet{\sheettag}}\fi%
+  \ifdefined\exf at label\label{\exf at label}\fi%
+%    \end{macrocode}
+% Set points from explicit input or from |.aux| storage:
+%    \begin{macrocode}
+  \ifdefined\exf at points@given%
+   \let\exf at data@sheet at rawpoints\exf at points@given%
+  \else\ifcsname exf at sheetpoints@\sheettag\endcsname%
+   \exf at csdotwo\let\exf at data@sheet at rawpoints{exf at sheetpoints@\sheettag}%
+  \fi\fi%
+%    \end{macrocode}
+% Process metadata:
+%    \begin{macrocode}
+  \def\exf at tmp{sheet}\ifx\exf at metadata\exf at tmp%
+   \exf at writemetadata{sheet}\fi%
+%    \end{macrocode}
+% Insert hook code:
+%    \begin{macrocode}
+  \exf at config@insertsheetbefore%
+%    \end{macrocode}
+% Add table of contents line:
+%    \begin{macrocode}
+  \ifx\exf at config@toclevelsheet\exf at empty\else%
+   \ifdefined\phantomsection\phantomsection\fi\fi%
+  \exf at addcontentsline{\exf at config@toclevelsheet}%
+   {\exf at config@composetocsheet{\csname the\exf at sheetcounter\endcsname}%
+    {\exf at data@sheet at rawtitle}}%
+%    \end{macrocode}
+% Write sheet title:
+%    \begin{macrocode}
+  \exf at config@insertsheettitle}%
+%    \end{macrocode}
+% End of environment;
+% perform sanity check on total points if given explicitly:
+%    \begin{macrocode}
+ {\ifdefined\exf at points@given%
+   \ifdim\exf at sheet@points at dim=0pt\else%
+    \ifdim\exf at sheet@points at dim=\exf at data@sheet at rawpoints pt\else%
+     \PackageWarning{exframe}{points mismatch for %
+      \exf at sheetname\space\csname the\exf at sheetcounter\endcsname}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at sheetname}%
+      {\strip at pt\exf at sheet@points at dim}{\exf at data@sheet at rawpoints}\fi%
+   \fi\fi%
+%    \end{macrocode}
+% Test whether points have changed since last compile:
+%    \begin{macrocode}
+  \else%
+   \ifx\exf at data@sheet at rawpoints\exf at empty\else%
+    \ifdim\exf at sheet@points at dim=\exf at data@sheet at rawpoints pt\else%
+     \PackageWarning{exframe}{points changed for %
+      \exf at sheetname\space\csname the\exf at sheetcounter\endcsname;
+      rerun to fix}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at sheetname}%
+      {\strip at pt\exf at sheet@points at dim}{\exf at data@sheet at rawpoints}\fi%
+   \fi\fi%
+%    \end{macrocode}
+% Store points if not given explicitly:
+%    \begin{macrocode}
+   \ifdim\exf at sheet@points at dim=0pt%
+    \def\exf at data@sheet at rawpoints{}%
+   \else%
+    \edef\exf at data@sheet at rawpoints{\strip at pt\exf at sheet@points at dim}%
+   \fi%
+  \fi%
+%    \end{macrocode}
+% Write sheet points to |.aux| file:
+%    \begin{macrocode}
+  \ifx\exf at data@sheet at rawpoints\exf at empty\else%
+   \exf at writesheetpoints{\exf at data@sheet at rawpoints}%
+  \fi%
+%    \end{macrocode}
+% Insert solutions:
+%    \begin{macrocode}
+  \exf at solbelowis{sheet}{\insertsolutions}%
+%    \end{macrocode}
+% Insert hook code:
+%    \begin{macrocode}
+  \exf at config@insertsheetafter%
+  \exf at config@insertsheetclearpage%
+%    \end{macrocode}
+% Restore original equation counter:
+%    \begin{macrocode}
+  \ifexf at style@sheetequation%
+   \setcounter{exf at sheetequation}{\value{equation}}%
+   \setcounter{equation}{\exf at eqsav}%
+  \fi%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \ignorespacesafterend}
+%    \end{macrocode}
+
+% \macro{\exercisecleardoublepage}
+% Clear the current page, clear even page with a totally empty page:
+%    \begin{macrocode}
+\newcommand{\exercisecleardoublepage}{%
+  \clearpage\ifexf at twoside\ifodd\value{page}\else%
+  \thispagestyle{empty}\hbox{}\newpage\fi\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problems.}
+%
+% \macro{\ifexf at problem@solnewsec}
+% Conditional to mark whether problem has been encountered:
+%    \begin{macrocode}
+\newif\ifexf at problem@solnewsec\exf at problem@solnewsectrue
+%    \end{macrocode}
+
+% \macro{exf at problem}
+% Define options for |problem| environment:
+%    \begin{macrocode}
+\define at key{exf at problem}{points}{\def\exf at points@given{#1}}
+\define at key{exf at problem}{label}{\def\exf at label{#1}}
+\define at key{exf at problem}{tag}{\def\problemtag{#1}}
+\define at key{exf at problem}{sollabel}{\xdef\exf at sollabel{#1}}
+%    \end{macrocode}
+
+% \macro{problem}
+% Define |problem| environment (potentially using custom name):
+%    \begin{macrocode}
+\newenvironment{\exf at problemname}[1][]{%
+%    \end{macrocode}
+% Start with new paragraph, set text style, add vspace and step counter:
+%    \begin{macrocode}
+  \par\exf at config@styletext%
+  \addvspace{\exf at config@skipproblemabove}%
+  \refstepcounter{\exf at problemcounter}%
+%    \end{macrocode}
+% Insert hook code, remember that a new problem was encountered:
+%    \begin{macrocode}
+  \exf at config@insertproblembefore%
+  \global\exf at problem@solnewsectrue%
+%    \end{macrocode}
+% Use equation counter for problems:
+%    \begin{macrocode}
+  \ifexf at style@problemequation%
+   \exf at eqsav\value{equation}%
+   \setcounter{equation}{\value{exf at problemequation}}%
+   \let\theequation\theexf at problemequation%
+   \let\theHequation\theHexf at problemequation%
+  \fi%
+%    \end{macrocode}
+% Start a block, mark in problem, initialise variables,
+% process arguments:
+%    \begin{macrocode}
+  \begingroup%
+  \def\exf at in@problem{}%
+  \exf at init@intro{\exf at config@skipprobleminfo}%
+  \def\problemtag{\csname the\exf at problemcounter\endcsname}%
+  \let\exf at points@given\@undefined%
+  \let\exf at label\@undefined%
+  \global\let\exf at sollabel\@undefined%
+  \setlength{\exf at problem@points at dim}{0pt}%
+  \setkeys{exf at problem,exf at probleminfo}{#1}%
+%    \end{macrocode}
+% Process automatic and manual labels:
+%    \begin{macrocode}
+  \ifexf at autolabelproblem\label{\exf at config@labelproblem{\problemtag}}\fi%
+  \ifdefined\exf at label\label{\exf at label}\fi%
+%    \end{macrocode}
+% Remember problem counter, title for solutions:
+%    \begin{macrocode}
+  \xdef\exf at prevprob{\csname the\exf at problemcounter\endcsname}%
+  \ifcsname theH\exf at problemcounter\endcsname%
+   \xdef\exf at prevprobhref{\exf at problemcounter.%
+    \csname theH\exf at problemcounter\endcsname}%
+  \fi%
+  \ifx\exf at data@problem at rawtitle\exf at empty%
+    \global\let\exf at prevprobtitle\@undefined%
+  \else%
+    \xdef\exf at prevprobtitle{\exf at data@problem at rawtitle}\fi%
+  \global\let\exf at prevsubprob\@undefined%
+  \global\let\exf at prevsubprobhref\@undefined%
+%    \end{macrocode}
+% Set points from explicit input or from |.aux| storage:
+%    \begin{macrocode}
+  \let\exf at problem@points\@undefined%
+  \ifdefined\exf at points@given%
+   \let\exf at problem@points\exf at points@given%
+  \else%
+   \ifcsname exf at problempoints@\problemtag\endcsname%
+    \exf at csdotwo\let\exf at problem@points{exf at problempoints@\problemtag}%
+  \fi\fi%
+  \global\let\exf at prevpoints\exf at problem@points%
+  \let\exf at problem@pointsshow\@undefined%
+  \ifdefined\exf at problem@points\ifdim\exf at problem@points pt=0pt\else%
+   \let\exf at problem@pointsshow\exf at problem@points%
+  \fi\fi%
+%    \end{macrocode}
+% Disable points display if desired:
+%    \begin{macrocode}
+  \exf at pointsatis{off}{\let\exf at problem@pointsshow\@undefined}%
+%    \end{macrocode}
+% Display points in opening line if desired;
+% expand points into argument and remove points:
+%    \begin{macrocode}
+  \exf at pointsatis{start}{\ifdefined\exf at problem@pointsshow%
+   \exf at exptwo\exf at append@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at problem@pointsshow}}%
+   \let\exf at problem@pointsshow\@undefined\fi}%
+  \exf at pointsatis{start*}{\ifdefined\exf at problem@pointsshow%
+   \exf at exptwo\exf at prepend@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at problem@pointsshow}}%
+   \let\exf at problem@pointsshow\@undefined\fi}%
+%    \end{macrocode}
+% Insert hook code, set problem body style:
+%    \begin{macrocode}
+  \exf at config@insertprobleminfo%
+  \exf at config@styletextproblem%
+%    \end{macrocode}
+% Write title without item:
+%    \begin{macrocode}
+  \ifdim\exf at config@skipproblemitem=0pt%
+   \exf at prepend@intro{{%
+    \exf at config@styletitle\exf at config@styletitleproblem%
+    \exf at config@composetitleproblem{\csname the\exf at problemcounter\endcsname}%
+     {\exf at data@problem at rawtitle}}}%
+%    \end{macrocode}
+% Write item with fixed total width or item width plus space:
+%    \begin{macrocode}
+  \else%
+   \ifdim\exf at config@skipproblemitem>0pt%
+    \setlength\exf at tmpdim{\exf at config@skipproblemitem}%
+   \else%
+    \settowidth\exf at tmpdim{%
+     \exf at config@styletitle\exf at config@styletitleproblem%
+     \exf at config@composeitemproblem{\exf at config@counterproblemmax}%
+     \exf at config@composeitemproblemsep}%
+   \fi%
+%    \end{macrocode}
+% Set up indentation:
+%    \begin{macrocode}
+   \advance\leftskip\exf at tmpdim%
+   \advance\linewidth -\exf at tmpdim%
+   \advance\@totalleftmargin\exf at tmpdim%
+%    \end{macrocode}
+% Define item label:
+%    \begin{macrocode}
+   \def\exf at introitem{\makebox[0cm][r]{%
+    \exf at config@styletitle\exf at config@styletitleproblem%
+    \exf at config@composeitemproblem{\csname the\exf at problemcounter\endcsname}%
+     \exf at config@composeitemproblemsep}}%
+%    \end{macrocode}
+% Compose title:
+%    \begin{macrocode}
+   \ifx\exf at data@problem at rawtitle\exf at empty\else%
+    \exf at prepend@intro{{%
+     \exf at config@styletitle\exf at config@styletitleproblem%
+     \exf at config@composetitleproblem{\exf at empty}{\exf at data@problem at rawtitle}}}%
+   \fi%
+  \fi%
+%    \end{macrocode}
+% Write points into margin if desired;
+% expand points into argument and remove points:
+%    \begin{macrocode}
+  \exf at pointsatis{margin}{\ifdefined\exf at problem@pointsshow%
+   \expandafter\exf at prepend@def\expandafter\exf at intro\expandafter%
+    {\expandafter\protect\expandafter%
+     \exf at config@insertpointsmargin\expandafter{\expandafter%
+      \exf at config@composepointsmargin\expandafter{\exf at problem@pointsshow}}}%
+   \let\exf at problem@pointsshow\@undefined\fi}%
+%    \end{macrocode}
+% Write out opening line:
+%    \begin{macrocode}
+  \exf at write@intro{\exf at config@skipproblemtitle}%
+%    \end{macrocode}
+% Add table of contents line:
+%    \begin{macrocode}
+  \exf at addcontentsline{\exf at config@toclevelproblem}%
+   {\exf at config@composetocproblem{\csname the\exf at problemcounter\endcsname}%
+    {\exf at data@problem at rawtitle}}%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \@afterindentfalse}%
+%    \end{macrocode}
+% End environment, show points if desired:
+%    \begin{macrocode}
+ {\exf at pointsatis{end}{\showpoints}%
+%    \end{macrocode}
+% Perform sanity checks on total points if given explicitly:
+%    \begin{macrocode}
+  \ifdefined\exf at points@given%
+   \ifdim\exf at problem@points at dim=0pt\else%
+    \ifdim\exf at problem@points at dim=\exf at problem@points pt\else%
+     \PackageWarning{exframe}{points mismatch for %
+      \exf at problemname\space\csname the\exf at problemcounter\endcsname}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at problemname}%
+      {\strip at pt\exf at problem@points at dim}{\exf at problem@points}\fi%
+   \fi\fi%
+%    \end{macrocode}
+% Warn if calculated total points have changed:
+%    \begin{macrocode}
+  \else%
+   \ifdefined\exf at problem@points%
+    \ifdim\exf at problem@points at dim=\exf at problem@points pt\else%
+     \PackageWarning{exframe}{points changed for %
+      \exf at problemname\space\csname the\exf at problemcounter\endcsname;
+      rerun to fix}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at problemname}%
+      {\strip at pt\exf at problem@points at dim}{\exf at problem@points}\fi%
+   \fi\fi%
+%    \end{macrocode}
+% Read computed total points, check whether zero:
+%    \begin{macrocode}
+   \ifdim\exf at problem@points at dim=0pt%
+    \let\exf at problem@points\@undefined%
+   \else%
+    \edef\exf at problem@points{\strip at pt\exf at problem@points at dim}%
+   \fi%
+  \fi%
+%    \end{macrocode}
+% Write points to |.aux| file; add to sheet total:
+%    \begin{macrocode}
+  \ifdefined\exf at problem@points%
+   \exf at writeproblempoints{\exf at problem@points}%
+   \global\addtolength{\exf at sheet@points at dim}{\exf at problem@points pt}%
+  \fi%
+%    \end{macrocode}
+% Warn if some but not all problems on sheet declare points:
+%    \begin{macrocode}
+  \ifdefined\exf at problem@points\else\ifdim\exf at sheet@points at dim=0pt\else%
+   \PackageWarning{exframe}{no points defined for \exf at problemname}%
+  \fi\fi%
+%    \end{macrocode}
+% End paragraph, insert hook code, vertical skip:
+%    \begin{macrocode}
+  \par\endgroup%
+  \exf at config@insertproblemafter%
+  \addvspace{\exf at config@skipproblembelow}%
+%    \end{macrocode}
+% Display solution if desired:
+%    \begin{macrocode}
+  \exf at solbelowis{problem}{%
+   \exf at showsolutions{\exf at config@composetitlesolutionmulti}{}}%
+%    \end{macrocode}
+% Solutions to subproblems should be declared within problem block:
+%    \begin{macrocode}
+  \global\let\exf at prevsubprob\@undefined%
+  \global\let\exf at prevsubprobhref\@undefined%
+%    \end{macrocode}
+% Restore original equation counter:
+%    \begin{macrocode}
+  \ifexf at style@problemequation%
+   \setcounter{exf at problemequation}{\value{equation}}%
+   \setcounter{equation}{\exf at eqsav}%
+  \fi%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \ignorespacesafterend}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Subproblems.}
+%
+% \macro{exf at subproblem}
+% Define options for |subproblem| environment:
+%    \begin{macrocode}
+\define at key{exf at subproblem}{points}{\def\exf at subproblem@points{#1}}
+\define at key{exf at subproblem}{label}{\def\exf at label{#1}}
+%    \end{macrocode}
+
+% \macro{subproblem}
+% Define |subproblem| environment (potentially using custom name):
+%    \begin{macrocode}
+\newenvironment{\exf at subproblemname}[1][]{%
+%    \end{macrocode}
+% Start with new paragraph, set text style, add vspace and step counter:
+%    \begin{macrocode}
+  \par%
+  {\exf at config@styletext\addvspace{\exf at config@skipsubproblemabove}}%
+  \refstepcounter{\exf at subproblemcounter}%
+%    \end{macrocode}
+% Insert hook code:
+%    \begin{macrocode}
+  \exf at config@insertsubproblembefore%
+%    \end{macrocode}
+% Remember subproblem counter for solution:
+%    \begin{macrocode}
+  \xdef\exf at prevsubprob{\csname the\exf at subproblemcounter\endcsname}%
+  \ifcsname theH\exf at subproblemcounter\endcsname%
+   \xdef\exf at prevsubprobhref{\exf at subproblemcounter.%
+    \csname theH\exf at subproblemcounter\endcsname}%
+  \fi%
+%    \end{macrocode}
+% Start a block, mark in subproblem, initialise variables,
+% process arguments:
+%    \begin{macrocode}
+  \begingroup%
+  \def\exf at in@subproblem{}%
+  \exf at init@intro{\exf at config@skipsubprobleminfo}%
+  \let\exf at subproblem@points\@undefined%
+  \let\exf at label\@undefined%
+  \setkeys{exf at subproblem,exf at probleminfo}{#1}%
+%    \end{macrocode}
+% Process manual label:
+%    \begin{macrocode}
+  \ifdefined\exf at label\label{\exf at label}\fi%
+%    \end{macrocode}
+% Add given points to problem total:
+%    \begin{macrocode}
+  \ifdefined\exf at subproblem@points%
+   \global\let\exf at prevpoints\exf at subproblem@points%
+   \global\addtolength{\exf at problem@points at dim}{\exf at subproblem@points pt}%
+%    \end{macrocode}
+% Warn if no points given for present subproblem but previously:
+%    \begin{macrocode}
+  \else%
+   \ifdim\exf at problem@points at dim=0pt\else%
+    \PackageWarning{exframe}{no points defined for \exf at subproblemname}%
+   \fi%
+  \fi%
+%    \end{macrocode}
+% Disable points display if desired:
+%    \begin{macrocode}
+  \exf at subpointsatis{off}{\let\exf at subproblem@points\@undefined}%
+%    \end{macrocode}
+% Display points in opening line if desired;
+% expand points into argument and remove points:
+%    \begin{macrocode}
+  \exf at subpointsatis{start}{\ifdefined\exf at subproblem@points%
+   \exf at exptwo\exf at append@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at subproblem@points}}%
+   \let\exf at subproblem@points\@undefined\fi}%
+  \exf at subpointsatis{start*}{\ifdefined\exf at subproblem@points%
+   \exf at exptwo\exf at prepend@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at subproblem@points}}%
+   \let\exf at subproblem@points\@undefined\fi}%
+%    \end{macrocode}
+% Insert hook code:
+%    \begin{macrocode}
+  \exf at config@insertsubprobleminfo%
+%    \end{macrocode}
+% Write opening line without item:
+%    \begin{macrocode}
+  \ifdim\exf at config@skipsubproblemitem=0pt%
+   \exf at prepend@intro{{%
+    \exf at config@styletitle\exf at config@styletitlesubproblem%
+    \exf at config@composetitlesubproblem{%
+     \csname the\exf at subproblemcounter\endcsname}}}%
+%    \end{macrocode}
+% Write item with fixed total width or item width plus space:
+%    \begin{macrocode}
+  \else%
+   \ifdim\exf at config@skipsubproblemitem>0pt%
+    \setlength\exf at tmpdim{\exf at config@skipsubproblemitem}%
+   \else%
+    \settowidth\exf at tmpdim{%
+     \exf at config@styletitle\exf at config@styletitlesubproblem%
+     \exf at config@composeitemsubproblem{\exf at config@countersubproblemmax}%
+     \exf at config@composeitemsubproblemsep}%
+   \fi%
+%    \end{macrocode}
+% Set up indentation:
+%    \begin{macrocode}
+   \advance\leftskip\exf at tmpdim%
+   \advance\linewidth -\exf at tmpdim%
+   \advance\@totalleftmargin\exf at tmpdim%
+%    \end{macrocode}
+% Define item label:
+%    \begin{macrocode}
+   \def\exf at introitem{\makebox[0cm][r]{%
+    \exf at config@styletitle\exf at config@styletitlesubproblem%
+    \exf at config@composeitemsubproblem%
+     {\csname the\exf at subproblemcounter\endcsname}%
+    \exf at config@composeitemsubproblemsep}}%
+  \fi%
+%    \end{macrocode}
+% Write points into margin if desired;
+% expand points into argument and remove points:
+%    \begin{macrocode}
+  \exf at subpointsatis{margin}{\ifdefined\exf at subproblem@points%
+   \expandafter\exf at prepend@def\expandafter\exf at intro\expandafter%
+    {\expandafter\protect\expandafter%
+     \exf at config@insertpointsmargin\expandafter{\expandafter%
+      \exf at config@composepointsmargin\expandafter{\exf at subproblem@points}}}%
+   \let\exf at subproblem@points\@undefined\fi}%
+%    \end{macrocode}
+% Write out opening line:
+%    \begin{macrocode}
+  \exf at write@intro{\exf at config@skipsubproblemtitle}%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \@afterindentfalse}%
+%    \end{macrocode}
+% End environment, show points if desired, end paragraph:
+%    \begin{macrocode}
+ {\exf at subpointsatis{end}{\showpoints}%
+  \par\endgroup%
+%    \end{macrocode}
+% Vertical skip, insert hook code:
+%    \begin{macrocode}
+  {\exf at config@styletext\addvspace{\exf at config@skipsubproblembelow}}%
+  \exf at config@insertsubproblemafter%
+%    \end{macrocode}
+% Display solution if desired:
+%    \begin{macrocode}
+  \exf at solbelowis{subproblem}{\exf at showsolutions%
+   {\exf at config@composetitlesolutionsingle}{}}%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \ignorespacesafterend}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Print Solutions.}
+%
+% \macro{exf at solution}
+% Define options for |solution| environment:
+%    \begin{macrocode}
+\define at key{exf at solution}{prob}{\def\exf at solprob{#1}}
+\define at key{exf at solution}{subprob}{\def\exf at solsubprob{#1}}
+\define at key{exf at solution}{problemtag}{\def\problemtag{#1}}
+\define at key{exf at solution}{sheettag}{\def\sheettag{#1}}
+\define at key{exf at solution}{href}{\def\exf at solhref{#1}}
+\define at key{exf at solution}{label}{\def\exf at label{#1}}
+\define at key{exf at solution}{points}{\def\exf at solution@points{#1}}
+\define at key{exf at solution}{probtitle}{\def\exf at solprobtitle{#1}}
+%    \end{macrocode}
+
+% \macro{printsolution}
+% Define |printsolution| environment
+% to display a previously read |solution| block;
+% this works analogously to |problem| and |subproblem|:
+%    \begin{macrocode}
+\newenvironment{printsolution}[1]{%
+%    \end{macrocode}
+% Start new paragraph, add vertical space, insert hook code:
+%    \begin{macrocode}
+  \par%
+  {\exf at config@styletext\addvspace{\exf at config@skipsolutionabove}}%
+  \exf at config@insertsolutionbefore%
+%    \end{macrocode}
+% Use equation counter for solutions:
+%    \begin{macrocode}
+  \ifexf at style@solutionequation%
+   \exf at eqsav\value{equation}%
+   \setcounter{equation}{\value{exf at solutionequation}}%
+   \let\theequation\theexf at solutionequation%
+   \let\theHequation\theHexf at solutionequation%
+  \fi%
+%    \end{macrocode}
+% Start a block, initialise variables, process arguments:
+%    \begin{macrocode}
+  \begingroup%
+  \def\exf at solprob{}%
+  \def\exf at solsubprob{}%
+  \let\exf at label\@undefined%
+  \setlength{\exf at solution@points at dim}{0pt}%
+  \def\exf at solhref{}%
+  \exf at init@intro{\exf at config@skipsolutioninfo}%
+  \setkeys{exf at solution,exf at probleminfo}{#1}%
+%    \end{macrocode}
+% Set solution counter to reflect associated problem:
+%    \begin{macrocode}
+  \exf at csdo\def{the\exf at solutioncounter}%
+   {\exf at config@composeitemsolution{\exf at solprob}{\exf at solsubprob}}%
+  \refstepcounter{\exf at solutioncounter}%
+%    \end{macrocode}
+% Set label:
+%    \begin{macrocode}
+  \ifdefined\exf at label\label{\exf at label}\fi%
+%    \end{macrocode}
+% Insert hook code, set solution body style:
+%    \begin{macrocode}
+  \exf at config@insertsolutioninfo%
+  \exf at config@styletext\exf at config@styletextsolution%
+%    \end{macrocode}
+% Determine solution for problem or subproblem:
+%    \begin{macrocode}
+  \ifx\exf at solsubprob\exf at empty%
+   \let\exf at tmp\exf at config@skipsolutionitem%
+  \else%
+   \let\exf at tmp\exf at config@skipsolutionitemsub%
+  \fi%
+%    \end{macrocode}
+% Write title without item:
+%    \begin{macrocode}
+  \ifdim\exf at tmp=0pt%
+   \protected at edef\exf at solution@title{%
+    \exf at composetitle{\exf at solprob}{\exf at solsubprob}}%
+   \ifx\exf at solution@title\exf at empty\else%
+    \exf at prepend@intro{{%
+     \exf at config@styletitle\exf at config@styletitlesolution%
+     \ifexf at solutionhref\exf at href{\exf at solhref}%
+      {\exf at solution@title}\else\exf at solution@title\fi}}%
+   \fi%
+%    \end{macrocode}
+% Write item with fixed total width or item width plus space:
+%    \begin{macrocode}
+  \else%
+   \ifdim\exf at tmp>0pt%
+    \setlength\exf at tmpdim{\exf at tmp}%
+   \else%
+    \settowidth\exf at tmpdim{%
+     \exf at config@styletitle\exf at config@styletitlesolution%
+     \ifx\exf at solsubprob\exf at empty%
+      \exf at config@composeitemsolution{\exf at config@counterproblemmax}%
+       {\exf at config@countersubproblemmax}%
+     \else%
+      \exf at config@composeitemsolutionsub{\exf at config@counterproblemmax}%
+       {\exf at config@countersubproblemmax}%
+     \fi\exf at config@composeitemsolutionsep}%
+   \fi%
+%    \end{macrocode}
+% Set up indentation:
+%    \begin{macrocode}
+   \advance\leftskip\exf at tmpdim%
+   \advance\linewidth -\exf at tmpdim%
+   \advance\@totalleftmargin\exf at tmpdim%
+%    \end{macrocode}
+% Set item label up depending on problem or subproblem:
+%    \begin{macrocode}
+   \ifx\exf at solsubprob\exf at empty%
+    \protected at edef\exf at solution@item%
+     {\exf at config@composeitemsolution{\exf at solprob}{\exf at empty}}%
+   \else%
+    \protected at edef\exf at solution@item%
+     {\exf at config@composeitemsolutionsub{\exf at solprob}{\exf at solsubprob}}%
+   \fi%
+%    \end{macrocode}
+% Define item label:
+%    \begin{macrocode}
+   \def\exf at introitem{\makebox[0cm][r]{%
+    \exf at config@styletitle\exf at config@styletitlesubproblem%
+    \ifexf at solutionhref\exf at href{\exf at solhref}{\exf at solution@item}%
+    \else\exf at solution@item\fi%
+    \exf at config@composeitemproblemsep}}%
+  \fi%
+%    \end{macrocode}
+% Write out opening line:
+%    \begin{macrocode}
+  \exf at write@intro{\exf at config@skipsolutiontitle}%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \@afterindentfalse}%
+%    \end{macrocode}
+% End environment, show points if desired, perform sanity check:
+%    \begin{macrocode}
+ {\ifdefined\exf at solution@points\ifdim\exf at solution@points at dim=0pt\else%
+   \ifdim\exf at solution@points at dim=\exf at solution@points pt\else%
+    \PackageWarning{exframe}{points mismatch in \exf at solutionname}%
+    \ifexf at warntext\exf at config@insertwarnpoints{\exf at solutionname}%
+     {\strip at pt\exf at solution@points at dim}{\exf at solution@points}\fi%
+  \fi\fi\fi%
+%    \end{macrocode}
+% End paragraph, vertical skip, insert hook code:
+%    \begin{macrocode}
+  \par\endgroup%
+  {\exf at config@styletext\addvspace{\exf at config@skipsolutionbelow}}%
+  \exf at config@insertsolutionafter%
+%    \end{macrocode}
+% Restore original equation counter:
+%    \begin{macrocode}
+  \ifexf at style@solutionequation%
+   \setcounter{exf at solutionequation}{\value{equation}}%
+   \setcounter{equation}{\exf at eqsav}%
+  \fi%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \ignorespacesafterend}
+%    \end{macrocode}
+
+% \macro{\solutionssection}
+% Define a section for a problem within a block with multiple solutions:
+%    \begin{macrocode}
+\newcommand{\solutionssection}[1]{\begingroup%
+%    \end{macrocode}
+% Initialise variables, process arguments:
+%    \begin{macrocode}
+  \def\exf at solprob{}%
+  \def\exf at solsubprob{}%
+  \def\exf at solprobtitle{}%
+  \let\exf at label\@undefined%
+  \let\exf at solhref\@undefined%
+  \setkeys{exf at solution}{#1}%
+%    \end{macrocode}
+% Select title (and table of contents entry)
+% corresponding to multiple problems vs. single problem:
+%    \begin{macrocode}
+  \let\exf at composetitle\exf at config@composetitlesolutionsproblemmulti%
+  \def\exf at solutionstoc{\exf at addcontentsline{\exf at config@toclevelsolution}%
+    {\exf at config@composetocsolution{\exf at solprob}{\exf at solprobtitle}}}%
+  \exf at solbelowis{problem}{\let\exf at composetitle%
+    \exf at config@composetitlesolutionsproblemsingle}%
+%    \end{macrocode}
+% Write section line:
+%    \begin{macrocode}
+  \exf at solutionssection{\exf at config@styletitlesolutionsproblem}%
+   {\exf at composetitle{\exf at solprob}{\exf at solprobtitle}}%
+   {\exf at config@skipsolutionsproblem}%
+   {\exf at solutionstoc}{\exf at label}{\exf at solhref}%
+  \endgroup}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Read Solution Block to Buffer.}
+%
+% \macro{solution}
+% Define |solution| environment (potentially using custom name);
+% pass on to |exf at scansolution| environment via
+% |\exf at scanblock| mechanism:
+%    \begin{macrocode}
+\newenvironment{\exf at solutionname}%
+  {\exf at scanblock{\exf at scansolution}}{\endexf at scansolution}%
+%    \end{macrocode}
+
+% \macro{exf at scansolution}
+% Define |exf at scansolution| to read solution to buffer and process:
+%    \begin{macrocode}
+\newenvironment{exf at scansolution}[2]{%
+%    \end{macrocode}
+% If solution is to be displayed immediately,
+% make sure to display points first:
+%    \begin{macrocode}
+  \exf at solbelowis{here}{\showpoints}%
+  \global\exf at bufcleanfalse%
+%    \end{macrocode}
+% If this is the first solution within a new section,
+% display section heading:
+%    \begin{macrocode}
+  \ifexf at problem@solnewsec%
+   \def\exf at probarg{\ifdefined\exf at prevprob prob={\exf at prevprob}\fi%
+    \ifdefined\exf at prevprobtitle,probtitle={\exf at prevprobtitle}\fi%
+    \ifdefined\exf at prevprobhref,href={\exf at prevprobhref}\fi%
+    \ifdefined\exf at sollabel,label={\exf at sollabel}\fi}%
+   \exf at solbelowis{here}{\let\exf at probarg\@undefined}%
+   \exf at solbelowis{subproblem}{\let\exf at probarg\@undefined}%
+   \ifdefined\exf at probarg%
+    \ifexf at lineno\exf at addbufline{\exf at linesep}\exf at addbufline{\exf at lineno}\fi%
+    \exf at addbufline{\@backslashchar solutionssection{\exf at probarg}}%
+    \exf at addbufline{}%
+   \fi%
+   \global\exf at problem@solnewsecfalse%
+  \fi%
+%    \end{macrocode}
+% Write separator to buffer:
+%    \begin{macrocode}
+  \ifexf at lineno\exf at addbufline{\exf at linesep}\exf at addbufline{\exf at lineno}\fi%
+%    \end{macrocode}
+% Declare additional arguments to |printsolution|
+% to describe corresponding problem and tags:
+%    \begin{macrocode}
+  \def\exf at subprobarg{%
+    \ifdefined\exf at prevprob prob={\exf at prevprob},\fi%
+    \ifdefined\exf at prevsubprob%
+     subprob={\exf at prevsubprob},%
+     \ifdefined\exf at prevsubprobhref href={\exf at prevsubprobhref},\fi%
+    \else%
+     \ifdefined\exf at prevprobhref href={\exf at prevprobhref},\fi%
+    \fi%
+    \ifdefined\exf at prevpoints points={\exf at prevpoints},\fi%
+    \ifdefined\sheettag sheettag={\sheettag},\fi%
+    \ifdefined\problemtag problemtag={\problemtag},\fi}%
+%    \end{macrocode}
+% Write |printsolution| opening to buffer:
+%    \begin{macrocode}
+  \exf at addbufline{\@backslashchar begin{printsolution}{\exf at subprobarg#1}}%
+%    \end{macrocode}
+% Clean up:
+%    \begin{macrocode}
+  \global\let\exf at prevsubprob\@undefined%
+  \global\let\exf at prevsubprobhref\@undefined%
+  \global\let\exf at prevpoints\@undefined%
+%    \end{macrocode}
+% Verbatim read block to buffer:
+%    \begin{macrocode}
+  \exf at verbatim#2}%
+%    \end{macrocode}
+% End environment; stop reading buffer:
+%    \begin{macrocode}
+ {\exf at endverbatim%
+%    \end{macrocode}
+% Write |printsolution| closing to buffer:
+%    \begin{macrocode}
+  \exf at addbufline{\@backslashchar end{printsolution}}%
+%    \end{macrocode}
+% Write buffer to file if output file open:
+%    \begin{macrocode}
+  \ifexf at infile%
+   \exf at writebuf%
+   \exf at clearbuf%
+  \fi%
+%    \end{macrocode}
+% Drop buffer if solutions not to be displayed:
+%    \begin{macrocode}
+  \ifsolutions\else\exf at clearbuf\fi%
+%    \end{macrocode}
+% Display solution immediately in various cases:
+%    \begin{macrocode}
+  \exf at solbelowis{here}{\exf at showsolutions%
+   {\exf at config@composetitlesolutionsingle}{}}%
+  \exf at solbelowis{subproblem}{\ifdefined\exf at in@subproblem\else%
+   \exf at showsolutions{\exf at config@composetitlesolutionsingle}{}\fi}%
+  \exf at solbelowis{problem}{\ifdefined\exf at in@problem\else%
+   \exf at showsolutions{\exf at config@composetitlesolutionmulti}{}\fi}%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \ignorespacesafterend}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solution Block Handling.}
+%
+% \macro{\exf at solutionssection}
+% Output solutions section:
+%    \begin{macrocode}
+\newcommand{\exf at solutionssection}[6]{%
+%    \end{macrocode}
+% Check whether title is empty:
+%    \begin{macrocode}
+  \protected at edef\exf at solutionstitleexp{#2}%
+  \ifx\exf at solutionstitleexp\exf at empty\else%
+%    \end{macrocode}
+% Define a label:
+%    \begin{macrocode}
+   \ifdefined#5%
+    \exf at csdo\def{the\exf at solutioncounter}%
+     {\exf at config@composeitemsolution{\exf at solprob}{\exf at solsubprob}}%
+    \refstepcounter{\exf at solutioncounter}\label{#5}%
+   \fi%
+%    \end{macrocode}
+% Output section line:
+%    \begin{macrocode}
+   \exf at section{#3}{\exf at config@styletitle\exf at config@styletitlesolution#1%
+    \ifexf at solutionhref\exf at href{#6}{\exf at solutionstitleexp}%
+    \else\exf at solutionstitleexp\fi}#4%
+  \fi}
+%    \end{macrocode}
+
+% \macro{\exf at solutionstitle}
+% Compose the title for a solution section:
+%    \begin{macrocode}
+\newcommand{\exf at solutionstitle}{\exf at solutionssection%
+  {\exf at config@styletitlesolutions}{%
+   \exf at config@composetitlesolutions}{\exf at config@skipsolutionstitle}%
+   {\exf at addcontentsline{\exf at config@toclevelsolutions}%
+    {\exf at config@composetocsolutions}}{\@undefined}{\@undefined}}
+%    \end{macrocode}
+
+% \macro{\exf at showsolutions}
+% Output solutions in buffer:
+%    \begin{macrocode}
+\newcommand{\exf at showsolutions}[2]{%
+%    \end{macrocode}
+% Do nothing if buffer is empty (avoid titles):
+%    \begin{macrocode}
+  \ifexf at bufclean\else\begingroup%
+%    \end{macrocode}
+% Set solution body style; add vertical space; insert hook code:
+%    \begin{macrocode}
+   \par\exf at config@styletext\addvspace{\exf at config@skipsolutionsabove}%
+   \exf at config@styletextsolution%
+   \exf at config@insertsolutionsbefore%
+   \let\exf at composetitle#1%
+   #2%
+%    \end{macrocode}
+% Source and clear buffer:
+%    \begin{macrocode}
+   \exf at sourcebuf%
+   \exf at clearbuf%
+%    \end{macrocode}
+% Ignore most recent skip; insert hook code;
+% close paragraph; add vertical space:
+%    \begin{macrocode}
+   \removelastskip%
+   \exf at config@insertsolutionsafter%
+   \par\exf at config@styletext\addvspace{\exf at config@skipsolutionbelow}%
+  \endgroup\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solutions Buffer Interface.}
+%
+% \macro{\writesolutions}
+% Open a file |#1.sol| for writing solutions;
+% default is present main file name:
+%    \begin{macrocode}
+\newcommand{\writesolutions}[1][\jobname]{\exf at closefile\exf at startfile{#1}}
+%    \end{macrocode}
+
+% \macro{\closesolutions}
+% Close output file (if open):
+%    \begin{macrocode}
+\newcommand{\closesolutions}{\exf at closefile}
+%    \end{macrocode}
+
+% \macro{\readsolutions}
+% Read solutions from file |#1.sol|;
+% default is present main file name;
+% switch layout and add heading:
+%    \begin{macrocode}
+\newcommand{\readsolutions}[1][\jobname]{\exf at closefile%
+  \ifsolutions\begingroup%
+   \exf at config@styletext\exf at config@styletextsolution%
+   \let\exf at config@composetitlesolution\exf at config@composetitlesolutionmulti%
+   \exf at solutionstitle%
+   \input{#1.sol}%
+  \endgroup\fi}
+%    \end{macrocode}
+
+% \macro{\insertsolutions}
+% Show solution buffer:
+%    \begin{macrocode}
+\newcommand{\insertsolutions}{\exf at showsolutions%
+  {\exf at config@composetitlesolutionmulti}{\exf at solutionstitle}}
+%    \end{macrocode}
+
+%\iffalse
+%</package>
+%\fi
+%
+\endinput


Property changes on: trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/exframe/exframe.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/exframe/exframe.ins	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/exframe/exframe.ins	2019-01-16 22:21:34 UTC (rev 49727)
@@ -0,0 +1,40 @@
+\def\batchfile{exframe.ins}
+\input docstrip.tex
+
+\keepsilent
+% exframe.ins Copyright (C) 2011-2019 Niklas Beisert
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+%   http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+
+\preamble
+
+Copyright (C) 2011-2019 Niklas Beisert
+
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in
+  http://www.latex-project.org/lppl.txt
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+\endpreamble
+
+% the style and sample files
+\generate{\askforoverwritefalse
+\file{exframe.sty}{\from{exframe.dtx}{package}}
+\file{exfsmp1.tex}{\from{exframe.dtx}{sample1}}
+\nopreamble\nopostamble
+}
+
+\Msg{***********************************************************************}
+\Msg{* Done. Please copy the file exframe.sty to an appropriate directory  *}
+\Msg{* of your LaTeX distribution, e.g. texmf-root/tex/latex/exframe.      *}
+\Msg{***********************************************************************}
+\endbatchfile

Added: trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty	2019-01-16 22:21:34 UTC (rev 49727)
@@ -0,0 +1,1155 @@
+%%
+%% This is file `exframe.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% exframe.dtx  (with options: `package')
+%% 
+%% Copyright (C) 2011-2019 Niklas Beisert
+%% 
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%%   http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%% 
+\NeedsTeXFormat{LaTeX2e}[1996/12/01]
+\ProvidesPackage{exframe}[2019/01/16 v3.0 Framework for Exercise Problems]
+
+\RequirePackage{verbatim}
+\RequirePackage{xkeyval}
+
+\def\exf at empty{}
+
+\newlength\exf at tmpdim
+
+\def\exf at exptwo#1{\expandafter#1\expandafter}
+\long\def\exf at expswitch#1#2{#2{#1}}
+\long\def\exf at exparg#1#2{\exf at exptwo\exf at expswitch{#2}{#1}}
+\def\exf at csdo#1#2{\expandafter#1\csname#2\endcsname}
+\def\exf at csdotwo#1#2#3{\exf at exptwo#1#2\csname#3\endcsname}
+
+\long\def\exf at append@def#1#2{\exf at exptwo\def#1\expandafter{#1#2}}
+\long\def\exf at prepend@switch#1#2#3{#2{#3#1}}
+\long\def\exf at prepend@def#1#2{\exf at exptwo\exf at prepend@switch{#1}{\def#1}{#2}}
+
+\newcommand{\exf at expsetkeys}[2]{\edef\exf at tmp{#2}%
+  \exf at exparg{\setkeys{#1}}{\exf at tmp}}
+
+\newcommand{\exf at href}[2]{%
+  \ifdefined#1\ifx#1\exf at empty#2\else%
+   \ifdefined\hyperlink\protect\hyperlink{#1}{#2}\else#2\fi\fi\else#2\fi}
+
+\newcommand{\exf at text}[1]{\ifdefined\text\text{#1}\else#1\fi}
+\newcommand{\exf at ensuretext}[1]{\ifmmode\mbox{#1}\else#1\fi}
+
+\newcommand{\exf at addcontentsline}[2]{%
+  \ifx#1\exf at empty\else\addcontentsline{toc}{#1}{#2}\fi}
+
+\def\exf at problemname{problem}
+\def\exf at subproblemname{sub\exf at problemname}
+\def\exf at solutionname{solution}
+\def\exf at sheetname{sheet}
+\def\exf at problemcounter{problem}
+\def\exf at subproblemcounter{sub\exf at problemcounter}
+\def\exf at solutioncounter{solution}
+\def\exf at sheetcounter{sheet}
+\define at key{exframe.sty}{problemenv}{\def\exf at problemname{#1}}
+\define at key{exframe.sty}{subproblemenv}{\def\exf at subproblemname{#1}}
+\define at key{exframe.sty}{solutionenv}{\def\exf at solutionname{#1}}
+\define at key{exframe.sty}{sheetenv}{\def\exf at sheetname{#1}}
+\define at key{exframe.sty}{problemcounter}{\def\exf at problemcounter{#1}}
+\define at key{exframe.sty}{subproblemcounter}{\def\exf at subproblemcounter{#1}}
+\define at key{exframe.sty}{solutioncounter}{\def\exf at solutioncounter{#1}}
+\define at key{exframe.sty}{sheetcounter}{\def\exf at sheetcounter{#1}}
+
+\define at boolkey{exframe.sty}[exf@]{extdata}[true]{}
+\define at boolkey{exframe.sty}[exf@]{extstyle}[true]{}
+
+\define at boolkey{exf at setup}[]{solutions}[true]{}
+\define at choicekey{exf at setup}{pdfdata}%
+  {auto,manual,sheet,off}[auto]{\def\exf at metadata{#1}}
+\def\exf at metadata{auto}
+\define at boolkey{exf at setup}[exf@]{lineno}[true]{}
+\define at boolkey{exf at setup}[exf@]{twoside}[true]{}
+\define at boolkey{exf at setup}[exf@]{solutionhref}[true]{}
+\exf at solutionhreftrue
+\define at boolkey{exf at setup}[exf@]{autolabelsheet}[true]{}
+\define at boolkey{exf at setup}[exf@]{autolabelproblem}[true]{}
+\define at boolkey{exf at setup}[exf@]{warntext}[true]{}
+
+\ProcessOptionsX<exframe.sty,exf at setup>
+
+\newcommand{\exercisesetup}[1]{\exf at expsetkeys{exf at setup}{#1}}
+
+\newcommand{\exerciseconfig}[1]{%
+  \@ifnextchar[{\exf at configopt{#1}}{\exf at confignoopt{#1}}}
+\long\def\exf at configopt#1[#2]#3{%
+  \exf at csdo\def{exf at config@#1}{}%
+  \exf at csdo\renewcommand{exf at config@#1}[#2]{#3}}%
+\long\def\exf at confignoopt#1#2{\exf at csdo\def{exf at config@#1}{#2}}
+\newcommand{\exerciseconfigappend}[2]{%
+  \exf at csdo\exf at append@def{exf at config@#1}{#2}}
+\newcommand{\exerciseconfigprepend}[2]{%
+  \exf at csdo\exf at prepend@def{exf at config@#1}{#2}}
+\newcommand{\getexerciseconfig}[1]{\csname exf at config@#1\endcsname}
+\newcommand{\exerciseconfigempty}[3]{\exf at csdo\ifx{exf at config@#1}\exf at empty%
+  #2\else#3\fi}
+
+\long\def\exerciseifempty#1#2#3{\if&#1&#2\else#3\fi}
+\long\def\exerciseifnotempty#1#2{\if&#1&\else#2\fi}
+
+\exerciseconfig{termsheet}{Sheet}
+\exerciseconfig{termsheets}{Sheets}
+\exerciseconfig{termproblem}{Problem}
+\exerciseconfig{termproblems}{Problems}
+\exerciseconfig{termsolution}{Solution}
+\exerciseconfig{termsolutions}{Solutions}
+\exerciseconfig{termpoint}{point}
+\exerciseconfig{termpoints}{points}
+
+\exerciseconfig{styletext}{\normalfont}
+\exerciseconfig{styletextproblem}{}
+\exerciseconfig{styletextsolution}{\footnotesize}
+\exerciseconfig{styletitle}{\bfseries}
+\exerciseconfig{styletitleproblem}{\large}
+\exerciseconfig{styletitlesubproblem}{}
+\exerciseconfig{styletitlesolution}{}
+\exerciseconfig{styletitlesolutionsproblem}{\small}
+\exerciseconfig{styletitlesolutions}{\normalsize}
+
+\exerciseconfig{skipproblemabove}{3.25ex plus 1ex minus 1.5ex}
+\exerciseconfig{skipproblembelow}{3pt plus 1pt minus 1pt}
+\exerciseconfig{skipproblemtitle}{3pt plus 1pt minus 1pt}
+\exerciseconfig{skipprobleminfo}{0.5em}
+\exerciseconfig{skipproblemitem}{0pt}
+
+\exerciseconfig{skipsubproblemabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsubproblembelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsubproblemtitle}{-1em}
+\exerciseconfig{skipsubprobleminfo}{0.25em}
+\exerciseconfig{skipsubproblemitem}{-1pt}
+
+\exerciseconfig{skipsolutionabove}{0ex}
+\exerciseconfig{skipsolutionbelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsolutiontitle}{-0.5em}
+\exerciseconfig{skipsolutioninfo}{0.25em}
+\exerciseconfig{skipsolutionitem}{0pt}
+\exerciseconfig{skipsolutionitemsub}{0pt}
+
+\exerciseconfig{skipsolutionsabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsolutionsbelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsolutionsproblem}{1.0ex plus 0ex minus 0.5ex}
+\exerciseconfig{skipsolutionstitle}{1.0ex plus 0ex minus 0.5ex}
+
+\exerciseconfig{insertsheettitle}{\centerline{\getsheetdata{title}}}
+\exerciseconfig{insertsheetclearpage}{\exercisecleardoublepage}
+\exerciseconfig{insertsheetbefore}{}
+\exerciseconfig{insertsheetafter}{}
+\exerciseconfig{insertsolutionsbefore}{}
+\exerciseconfig{insertsolutionsafter}{}
+\exerciseconfig{insertproblembefore}{}
+\exerciseconfig{insertproblemafter}{}
+\exerciseconfig{insertprobleminfo}{}
+\exerciseconfig{insertsubproblembefore}{}
+\exerciseconfig{insertsubproblemafter}{}
+\exerciseconfig{insertsubprobleminfo}{}
+\exerciseconfig{insertsolutionbefore}{}
+\exerciseconfig{insertsolutionafter}{}
+\exerciseconfig{insertsolutioninfo}{}
+
+\exerciseconfig{composeitemsep}{\ }
+\exerciseconfig{composetitlesheet}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
+\exerciseconfig{composemetasheet}[2]%
+  {\getexerciseconfig{composetitlesheet}{#1}{#2}}
+\exerciseconfig{composetocsheet}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#1. #2}}
+\exerciseconfig{composeitemproblem}[1]{#1.}
+\exerciseconfig{composeitemproblemsep}%
+  {\getexerciseconfig{composeitemsep}}
+\exerciseconfig{composetitleproblem}[2]{\exerciseifempty{#1}%
+   {\exerciseifempty{#2}{}{#2}}%
+   {\exerciseifempty{#2}{\getexerciseconfig{termproblem}\ %
+     \getexerciseconfig{composeitemproblem}{#1}}%
+    {\getexerciseconfig{composeitemproblem}{#1} #2}}}
+\exerciseconfig{composetocproblem}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termproblem} #1}{#1. #2}}
+\exerciseconfig{composeitemsubproblem}[1]{#1}
+\exerciseconfig{composeitemsubproblemsep}%
+  {\getexerciseconfig{composeitemsep}}
+\exerciseconfig{composetitlesubproblem}[1]{#1}
+\exerciseconfig{composeitemsolution}[2]{#1.}
+\exerciseconfig{composeitemsolutionsub}[2]{#2}
+\exerciseconfig{composeitemsolutionsep}%
+  {\getexerciseconfig{composeitemsep}}
+\exerciseconfig{composetitlesolutionsingle}[2]%
+  {\getexerciseconfig{termsolution}:}
+\exerciseconfig{composetitlesolutionmulti}[2]{#2}
+\exerciseconfig{composetocsolution}[2]%
+  {\getexerciseconfig{composetocproblem}{#1}{#2}}
+\exerciseconfig{composetitlesolutions}%
+  {\getexerciseconfig{termsolutions}}
+\exerciseconfig{composetocsolutions}%
+  {\getexerciseconfig{composetitlesolutions}}
+\exerciseconfig{composetitlesolutionsproblemsingle}[2]%
+  {\getexerciseconfig{termsolution}}
+\exerciseconfig{composetitlesolutionsproblemmulti}[2]%
+  {\exerciseifempty{#2}{\getexerciseconfig{termproblem} #1}{#1. #2}}
+\exerciseconfig{composeitemsolution}[2]{#1#2}
+
+\exerciseconfig{composepointsnum}[1]{#1}
+\exerciseconfig{composepoints}[1]{\getexerciseconfig{composepointsnum}{#1}~%
+  \ifdim #1pt=1pt\getexerciseconfig{termpoint}%
+  \else\getexerciseconfig{termpoints}\fi}
+\exerciseconfig{composepointsstart}[1]{(\getexerciseconfig{composepoints}{#1})}
+\exerciseconfig{composepointsmargin}[1]{\getexerciseconfig{composepoints}{#1}}
+\exerciseconfig{composepointsbody}[1]{(\getexerciseconfig{composepoints}{#1})}
+\exerciseconfig{composepointssheet}[1]{%
+  \exerciseifnotempty{#1}{\getexerciseconfig{composepoints}{#1}}}
+\exerciseconfig{composepointsaward}[2]%
+  {(\getexerciseconfig{composepoints}{#1}\exerciseifnotempty{#2}{; #2})}
+\exerciseconfig{composepointsawardalt}[2]%
+  {(\getexerciseconfig{composepoints}{#1}*\exerciseifnotempty{#2}{; #2})}
+
+\exerciseconfig{insertpointsmargin}[1]{\marginpar{\footnotesize #1}}
+
+\exerciseconfig{insertwarnpoints}[3]
+  {\textbf{points mismatch for #1 (#2 determined vs.\ #3 given)}}
+
+\exerciseconfig{countersheet}{\arabic{\exf at sheetcounter}}
+\exerciseconfig{counterproblem}{\arabic{\exf at problemcounter}}
+\exerciseconfig{counterproblemmax}{10}
+\exerciseconfig{countersubproblem}{\alph{\exf at subproblemcounter})}
+\exerciseconfig{countersubproblemmax}{m)}
+\exerciseconfig{countersheetequation}{\arabic{equation}}
+\exerciseconfig{counterproblemequation}{P\arabic{equation}}
+\exerciseconfig{countersolutionequation}{S\arabic{equation}}
+
+\exerciseconfig{labelsheet}[1]{sheet:#1}
+\exerciseconfig{labelproblem}[1]{prob:#1}
+
+\exerciseconfig{toclevelsheet}{}
+\exerciseconfig{toclevelproblem}{}
+\exerciseconfig{toclevelsolution}{}
+\exerciseconfig{toclevelsolutions}{}
+
+\newcommand{\defexercisestylearg}[3][]{%
+  \def\exf at tmp{#1}\ifx\exf at tmp\exf at empty%
+   \define at key{exf at style}{#2}{#3}\else%
+   \define at key{exf at style}{#2}[#1]{#3}\fi}
+\newcommand{\defexercisestyle}[2]{%
+  \exf at csdotwo\long\def{exf at style@code@#1}{#2}%
+  \exf at exparg{\define at boolkey{exf at style}[exf at style@]{#1}[true]}%
+   {\csname ifexf at style@#1\endcsname\csname exf at style@code@#1\endcsname\fi}}
+\newcommand{\exercisestyle}[1]{\exf at expsetkeys{exf at style}{#1}}
+
+\def\exf at solutionbelow{subproblem}
+\define at choicekey{exf at style}{solutionbelow}%
+  {here,subproblem,problem,sheet,manual}{\def\exf at solutionbelow{#1}}
+\newcommand{\exf at solbelowis}[2]%
+  {\def\exf at tmp{#1}\ifx\exf at solutionbelow\exf at tmp#2\fi}
+\defexercisestyle{sheetequation}{}
+\defexercisestyle{problemequation}{}
+\defexercisestyle{solutionequation}{}
+\exf at style@solutionequationtrue
+\def\exf at pointsat{start}
+\define at choicekey{exf at style}{pointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at pointsat{#1}}
+\def\exf at subpointsat{end}
+\define at choicekey{exf at style}{subpointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at subpointsat{#1}}
+\newcommand{\exf at pointsatis}[2]%
+  {\def\exf at tmp{#1}\ifx\exf at pointsat\exf at tmp#2\fi}
+\newcommand{\exf at subpointsatis}[2]%
+  {\def\exf at tmp{#1}\ifx\exf at subpointsat\exf at tmp#2\fi}
+\defexercisestylearg{problemby}{\exf at numberproblemwithin{#1}}
+\defexercisestylearg{equationby}{\exf at numberequationwithin{#1}}
+\defexercisestyle{pagebysheet}{%
+  \def\thepage{\csname the\exf at sheetcounter\endcsname.\arabic{page}}%
+  \def\theHpage{\csname theH\exf at sheetcounter\endcsname.\arabic{page}}%
+  \exerciseconfigappend{insertsheetbefore}{\setcounter{page}{1}}}
+\defexercisestyle{problembysheet}%
+  {\exf at numberproblemwithin{\exf at sheetcounter}}
+\defexercisestyle{equationbysheet}%
+  {\exf at numberequationwithin{\exf at sheetcounter}}
+\defexercisestyle{fracpoints}%
+  {\exerciseconfig{composepointsnum}[1]{\exf at nicefrac{##1}}}
+\defexercisestylearg[true]{twoside}{\exercisesetup{twoside={#1}}}
+
+\ifexf at extstyle
+\defexercisestyle{contents}{%
+  \exerciseconfig{toclevelsheet}{section}%
+  \exerciseconfig{toclevelproblem}{subsection}}
+\defexercisestyle{solutionsf}{%
+  \exerciseconfigappend{styletextsolution}{\sffamily\let\itshape\slshape}}
+\defexercisestyle{solutiondimproblem}{%
+  \RequirePackage{color}%
+  \exerciseconfigappend{styletextsolution}{\color[gray]{0}}%
+  \exerciseconfigappend{styletextproblem}{\color[gray]{0.2}}}
+\defexercisestyle{solutionsep}{%
+  \exerciseconfig{insertsolutionsbefore}{\hrule\nopagebreak[3]\vspace{0.5ex}}%
+  \exerciseconfig{insertsolutionsafter}{\nopagebreak[3]\vspace{1.0ex}\hrule}}
+\defexercisestyle{plainheader}{%
+  \exerciseconfig{styleheadertitle}{\Large\bfseries}%
+  \exerciseconfig{styleheadercourse}{\sffamily}%
+  \exerciseconfig{styleheaderbelow}{\footnotesize}%
+  \exerciseconfig{skipheaderbelow}{3ex}%
+  \exerciseconfig{composeheaderbelowleft}{}%
+  \exerciseconfig{composeheaderbelowright}{}%
+  \exerciseconfig{composeheaderbelowcenter}{}%
+  \exerciseconfig{insertsheettitle}{\noindent%
+   \begin{minipage}{\textwidth}%
+   {\getexerciseconfig{styleheadertitle}%
+    \makebox[0pt][l]{\getexercisedata{course}}%
+    \hfill\makebox[0pt][r]{\getsheetdata{title}}\par}%
+   {\getexerciseconfig{styleheadercourse}%
+    \makebox[0pt][l]{\getexercisedata{institution}%
+     \exercisedataempty{period}{}{, \getexercisedata{period}}}%
+    \hfill\makebox[0pt][r]{\getexercisedata{instructor}}%
+    \vphantom{g}\par}%
+   \hrule%
+   {\def\tmp{}%
+    \exerciseconfigempty{composeheaderbelowleft}{}{\def\tmp{.}}%
+    \exerciseconfigempty{composeheaderbelowcenter}{}{\def\tmp{.}}%
+    \exerciseconfigempty{composeheaderbelowright}{}{\def\tmp{.}}%
+    \exerciseifnotempty{\tmp}%
+     {\getexerciseconfig{styleheaderbelow}\vphantom{\^A}%
+      \makebox[0pt][l]{\getexerciseconfig{composeheaderbelowleft}}%
+      \hfill\makebox[0pt][c]{\getexerciseconfig{composeheaderbelowcenter}}%
+      \hfill\makebox[0pt][r]{\getexerciseconfig{composeheaderbelowright}}%
+      \vspace*{-\baselineskip}\vspace*{-\parskip}\par}}%
+   \end{minipage}%
+   \par\addvspace{\getexerciseconfig{skipheaderbelow}}}}
+\fi
+
+\newcommand{\defexercisedata}[1]{%
+  \exf at csdo\def{exf at data@#1}{}%
+  \define at key{exf at data}{#1}%
+   {\exf at csdo\gdef{exf at data@#1}{##1}}}
+\newcommand{\exercisedata}[1]{\setkeys{exf at data}{#1}}
+\newcommand{\getexercisedata}[1]{\csname exf at data@#1\endcsname}
+\newcommand{\exercisedataempty}[3]{\exf at csdo\ifx{exf at data@#1}\exf at empty%
+  #2\else#3\fi}
+
+\defexercisedata{author}
+\defexercisedata{title}
+\defexercisedata{subject}
+\defexercisedata{keyword}
+\defexercisedata{date}
+\defexercisedata{instructor}
+\defexercisedata{course}
+\defexercisedata{institution}
+\defexercisedata{period}
+\defexercisedata{material}
+\define at key{exf at data}{author}{\gdef\exf at data@author{#1}\author{#1}}
+\define at key{exf at data}{title}{\gdef\exf at data@title{#1}\title{#1}}
+\define at key{exf at data}{date}{\gdef\exf at data@date{#1}\date{#1}}
+
+\newcommand{\defsheetdata}[1]{%
+  \exf at csdo\def{exf at data@sheet@#1}{}%
+  \define at key{exf at sheet}{#1}%
+   {\exf at csdo\def{exf at data@sheet@#1}{##1}}}
+\newcommand{\getsheetdata}[1]{\csname exf at data@sheet@#1\endcsname}
+\newcommand{\sheetdataempty}[3]{\exf at csdo\ifx{exf at data@sheet@#1}\exf at empty%
+  #2\else#3\fi}
+
+\defsheetdata{due}
+\defsheetdata{handout}
+\defsheetdata{editdate}
+\defsheetdata{author}
+\defsheetdata{editor}
+
+\def\exf at data@sheet at rawtitle{}
+\define at key{exf at sheet}{title}{\def\exf at data@sheet at rawtitle{#1}}
+\def\exf at data@sheet at title{\exf at config@composetitlesheet%
+  {\csname the\exf at sheetcounter\endcsname}{\exf at data@sheet at rawtitle}}%
+\def\exf at data@sheet at rawpoints{}
+\def\exf at data@sheet at points{\exf at config@composepointssheet%
+  {\exf at data@sheet at rawpoints}}%
+
+\newcommand{\defproblemdata}[1]{%
+  \exf at csdo\def{exf at data@problem@#1}{}%
+  \define at key{exf at problem}{#1}%
+   {\exf at csdo\def{exf at data@problem@#1}{##1}}}
+\newcommand{\getproblemdata}[1]{\csname exf at data@problem@#1\endcsname}
+\newcommand{\problemdataempty}[3]{\exf at csdo\ifx{exf at data@problem@#1}\exf at empty%
+  #2\else#3\fi}
+
+\def\exf at data@problem at rawtitle{}
+\define at key{exf at problem}{title}{\def\exf at data@problem at rawtitle{#1}}
+\def\exf at data@problem at title{\exf at config@composetitleproblem{%
+ \csname the\exf at problemcounter\endcsname}{\exf at data@problem at rawtitle}}%
+
+\newcommand{\exf at section}[2]{\setlength\exf at tmpdim{#1}%
+  \ifdim\exf at tmpdim<0pt%
+   \protected at edef\exf at tmp{#2}%
+  \else%
+   \def\exf at tmp{#2}%
+  \fi%
+  \exf at exparg{\@startsection{}{}{0pt}{0pt}{#1}{}*}{\exf at tmp}}
+
+\newcommand{\exf at init@intro}[1]%
+  {\def\exf at intro{}\def\exf at introitem{}\def\exf at intro@skip{#1}}
+\newcommand{\exf at append@intro}[1]%
+  {\exf at append@def\exf at intro{#1\hspace{\exf at intro@skip}}}
+\newcommand{\exf at prepend@intro}[1]%
+  {\exf at prepend@def\exf at intro{#1\hspace{\exf at intro@skip}}}
+\newcommand{\exf at write@intro}[1]{%
+  \ifx\exf at intro\exf at empty%
+   \exf at section{0pt}{\exf at introitem}%
+  \else%
+   \exf at section{#1}{\exf at introitem\exf at intro\unskip}%
+  \fi}%
+
+\newcommand{\addprobleminfo}{\@ifstar\exf at prepend@intro\exf at append@intro}
+
+\newcommand{\exf at addinfoswitch}[1]%
+  {\define at boolkey{exf at infoswitch}[exf at showdata@]{#1}[true]{}}
+\newcommand{\defprobleminfo}[2]{%
+  \exf at addinfoswitch{#1}%
+  \exerciseconfig{compose at probleminfo@#1}[1]{#2}%
+  \exf at exparg{\define at key{exf at probleminfo}{#1}}%
+   {\csname ifexf at showdata@#1\endcsname\exf at append@intro{%
+    \csname exf at config@compose at probleminfo@#1\endcsname{##1}}\fi}}
+\newcommand{\showprobleminfo}[1]{\exf at expsetkeys{exf at infoswitch}{#1}}
+
+\defprobleminfo{optional}{\emph{#1:}}
+\showprobleminfo{optional}
+\defprobleminfo{difficulty}{(#1)}
+
+\defprobleminfo{comment}{#1}
+\defprobleminfo{author}{$\langle$#1$\rangle$}
+\defprobleminfo{editor}{$\{$#1$\}$}
+\defprobleminfo{source}{[#1]}
+\defprobleminfo{keyword}{\#(#1)}
+
+\ifexf at extdata
+\defprobleminfo{review}{#1}
+\defprobleminfo{recycle}{[[#1]]}
+\defprobleminfo{timesolve}{\{#1\}}
+\defprobleminfo{timepresent}{\{\!\{#1\}\!\}}
+\fi
+
+\newcommand{\exf at writemetadata}[1]{%
+  \ifdefined\hypersetup%
+   \def\exf at tmp{#1}\ifx\exf at tmp\exf at empty%
+    \ifx\exf at data@author\exf at empty\else%
+     \hypersetup{pdfauthor={\exf at data@author}}\fi%
+    \ifx\exf at data@title\exf at empty\else%
+     \hypersetup{pdftitle={\exf at data@title}}\fi%
+   \else%
+    \ifx\exf at data@sheet at author\exf at empty%
+     \ifx\exf at data@author\exf at empty\else%
+      \hypersetup{pdfauthor={\exf at data@author}}\fi%
+    \else\hypersetup{pdfauthor={\exf at data@sheet at author}}\fi%
+    \hypersetup{pdftitle={\exf at config@composemetasheet%
+     {\csname the\exf at sheetcounter\endcsname}{\exf at data@sheet at rawtitle}}}%
+   \fi%
+   \ifx\exf at data@subject\exf at empty\else%
+    \hypersetup{pdfsubject={\exf at data@subject}}\fi%
+   \ifx\exf at data@keyword\exf at empty\else%
+    \hypersetup{pdfkeywords={\exf at data@keyword}}\fi%
+  \fi%
+  \gdef\exf at metadata{off}}
+
+\AtBeginDocument{\def\exf at tmp{auto}\ifx\exf at metadata\exf at tmp%
+  \exf at writemetadata{}\fi}
+
+\newcommand{\writeexercisedata}{\def\exf at tmp{manual}\ifx\exf at metadata\exf at tmp%
+  \exf at writemetadata{}\fi}
+
+\newcounter{\exf at sheetcounter}
+\newcounter{\exf at problemcounter}
+\newcounter{\exf at subproblemcounter}[\exf at problemcounter]
+\newcounter{\exf at solutioncounter}[\exf at problemcounter]
+\newcount\exf at eqsav
+\newcounter{exf at sheetequation}
+\newcounter{exf at problemequation}
+\newcounter{exf at solutionequation}
+
+\exf at csdo\def{the\exf at sheetcounter}{\exf at config@countersheet}
+\exf at csdo\def{the\exf at problemcounter}{\exf at config@counterproblem}
+\exf at csdo\def{the\exf at subproblemcounter}{\exf at config@countersubproblem}
+\def\theexf at sheetequation{\exf at config@countersheetequation}
+\def\theHexf at sheetequation{sheet.\arabic{equation}}
+\def\theexf at problemequation{\exf at config@counterproblemequation}
+\def\theHexf at problemequation{prob.\arabic{equation}}
+\def\theexf at solutionequation{\exf at config@countersolutionequation}
+\def\theHexf at solutionequation{sol.\arabic{equation}}
+
+\newcommand{\exf at numberproblemwithin}[1]{%
+  \@addtoreset{\exf at problemcounter}{#1}%
+  \exf at csdo\def{the\exf at problemcounter}%
+   {\csname the#1\endcsname.\exf at config@counterproblem}}
+
+\newcommand{\exf at numberequationwithin}[1]{%
+  \@addtoreset{exf at sheetequation}{#1}%
+  \def\theexf at sheetequation%
+   {\csname the#1\endcsname.\exf at config@countersheetequation}%
+  \def\theHexf at sheetequation%
+   {\csname theH#1\endcsname.sheet.\arabic{equation}}%
+  \@addtoreset{exf at problemequation}{#1}%
+  \def\theexf at problemequation%
+   {\csname the#1\endcsname.\exf at config@counterproblemequation}%
+  \def\theHexf at problemequation%
+   {\csname theH#1\endcsname.prob.\arabic{equation}}%
+  \@addtoreset{exf at solutionequation}{#1}%
+  \def\theexf at solutionequation%
+   {\csname the#1\endcsname.\exf at config@countersolutionequation}%
+  \def\theHexf at solutionequation%
+   {\csname theH#1\endcsname.sol.\arabic{equation}}}
+
+\newif\ifexf at infile\exf at infilefalse
+\newwrite\exf at out
+
+\newcommand{\exf at writeline}[1]{\immediate\write\exf at out{#1}}
+
+\newcommand{\exf at linesep}%
+  {\@percentchar---------------------------------------}
+\newcommand{\exf at lineno}{\@percentchar%
+  \ifdefined\currfilename\currfilename\space\fi%
+  l.\the\inputlineno}
+
+\newcommand{\exf at startfile}[1]{%
+  \ifexf at infile\else%
+   \global\exf at infiletrue%
+   \gdef\exf at solutionbelow{manual}%
+   \edef\exf at tmp{#1}%
+   \immediate\openout\exf at out\exf at tmp.sol%
+   \exf at writeline{\@percentchar%
+    generated from file `\jobname' by exframe.sty}%
+   \ifexf at lineno\exf at writeline{\exf at lineno}\fi%
+   \exf at writeline{}%
+  \fi}
+
+\newcommand{\exf at closefile}{%
+  \ifexf at infile%
+   \ifexf at lineno%
+    \exf at writeline{\exf at linesep}\exf at writeline{\exf at lineno}\fi%
+   \exf at writeline{\@backslashchar endinput}%
+   \immediate\closeout\exf at out%
+   \global\exf at infilefalse%
+  \fi}
+
+\AtEndDocument{\exf at closefile}
+
+\newtoks\exf at buf
+\newif\ifexf at bufclean\exf at bufcleantrue
+
+\def\exf at clearbuf{\global\exf at bufcleantrue\global\exf at buf={}}
+\def\exf at append@buf#1{\global\exf at buf=\expandafter{\the\exf at buf#1}}
+\def\exf at addbufline#1{{\protected at edef\exf at tmp{#1}%
+  \exf at exptwo\exf at append@buf{\exf at tmp^^J}}}
+
+\def\exf at sourcebuf{\exf at exptwo\scantokens{\the\exf at buf}}
+\def\exf at writebuf{\exf at writeline{\the\exf at buf}}
+
+\newcommand{\exf at verbatim}{%
+  \begingroup%
+  \@bsphack%
+  \let\do\@makeother\dospecials%
+  \catcode`\^^M\active%
+  \def\verbatim at processline{\exf at exptwo\exf at append@buf{\the\verbatim at line^^J}}%
+  \verbatim at start}
+
+\newcommand{\exf at endverbatim}{\@esphack\endgroup}
+
+\def\exf at scanblock#1{%
+  \@ifnextchar\par{\exf at scanblock@par{#1}}{\exf at scanblock@sel{#1}}}
+\long\def\exf at scanblock@par#1\par{\exf at scanblock@sel{#1}[]}
+\def\exf at scanblock@sel#1{\@ifnextchar[{\exf at scanblock@opt{#1}}%
+  {\@ifnextchar\end{\exf at scanblock@end{#1}}{\exf at scanblock@noopt{#1}}}}
+\def\exf at scanblock@end#1\end#2{%
+  \def\exf at tmp{#2}\ifx\exf at tmp\@currenvir%
+    \def\exf at verbatim{}\def\exf at endverbatim{}%
+  \fi%
+  #1{}{\scantokens{\end{#2}}}}
+\def\exf at scanblock@noopt#1#2{#1{}{\scantokens#2}}
+\def\exf at scanblock@opt#1[#2]{#1{#2}{}}
+
+\def\exf at splitsign#1-#2-#3&{\def\exf at splitnum{#1#2}\def\exf at splitminus{#3}}
+\def\exf at splitdecimal#1.#2.#3&{\def\exf at splitint{#1}\def\exf at splitdec{#2}}
+
+\newcommand{\exf at nicefrac}[1]{%
+  \edef\exf at tmp{#1}%
+  \expandafter\exf at splitsign\exf at tmp--&%
+  \expandafter\exf at splitdecimal\exf at splitnum..&%
+  \if&\exf at splitint&\def\exf at splitint{0}\fi%
+  \if&\exf at splitdec&\def\exf at splitdec{0}\fi%
+  \def\exf at tmp{\exf at splitint.\exf at splitdec}%
+  \ifnum\exf at splitdec=0\def\exf at tmp{\exf at splitint}\fi%
+  \ifnum\exf at splitdec=5\def\exf at tmp{\exf at intfrac{\exf at splitint}{1}{2}}\fi%
+  \ifnum\exf at splitdec=25\def\exf at tmp{\exf at intfrac{\exf at splitint}{1}{4}}\fi%
+  \ifnum\exf at splitdec=75\def\exf at tmp{\exf at intfrac{\exf at splitint}{3}{4}}\fi%
+  \ifnum\exf at splitdec=125\def\exf at tmp{\exf at intfrac{\exf at splitint}{1}{8}}\fi%
+  \ifnum\exf at splitdec=375\def\exf at tmp{\exf at intfrac{\exf at splitint}{3}{8}}\fi%
+  \ifnum\exf at splitdec=625\def\exf at tmp{\exf at intfrac{\exf at splitint}{5}{8}}\fi%
+  \ifnum\exf at splitdec=875\def\exf at tmp{\exf at intfrac{\exf at splitint}{7}{8}}\fi%
+  \ifx\exf at splitminus\exf at empty\else$\exf at splitminus$\fi\exf at tmp%
+}
+
+\newcommand{\exf at intfrac}[3]{%
+  \ifnum#1=0\else#1\fi%
+  \ifnum#2=0\else$%
+   ^{\exf at text{#2}}%
+   \mskip-4mu/\mskip-2mu%
+   _{\exf at text{#3}}$\fi}
+
+\newlength{\exf at sheet@points at dim}
+\newcommand{\exf at notesheetpoints}[2]{%
+  \exf at csdo\gdef{exf at sheetpoints@#1}{#2}}
+\AtBeginDocument{\immediate\write\@auxout{%
+  \string\providecommand{\string\exf at notesheetpoints}[2]{}}}
+\newcommand{\exf at writesheetpoints}[1]%
+  {\immediate\write\@auxout{\string\exf at notesheetpoints{\sheettag}{#1}}}
+\newcommand{\getsheetpoints}[1]{\ifcsname exf at sheetpoints@#1\endcsname%
+  \csname exf at sheetpoints@#1\endcsname\else 0\fi}
+
+\newlength{\exf at problem@points at dim}
+\newcommand{\exf at noteproblempoints}[2]{%
+  \exf at csdo\gdef{exf at problempoints@#1}{#2}}
+\AtBeginDocument{\immediate\write\@auxout{%
+  \string\providecommand{\string\exf at noteproblempoints}[2]{}}}
+\newcommand{\exf at writeproblempoints}[1]%
+  {\immediate\write\@auxout{\string\exf at noteproblempoints{\problemtag}{#1}}}
+\newcommand{\getproblempoints}[1]{\ifcsname exf at problempoints@#1\endcsname%
+  \csname exf at problempoints@#1\endcsname\else 0\fi}
+
+\newcommand{\showpoints}{%
+  \ifdefined\exf at in@subproblem%
+   \ifdefined\exf at subproblem@points%
+    \exf at ensuretext{\exf at config@composepointsbody{\exf at subproblem@points}}%
+    \global\let\exf at subproblem@points\@undefined%
+   \fi%
+  \else\ifdefined\exf at in@problem%
+   \ifdefined\exf at problem@pointsshow%
+    \exf at ensuretext{\exf at config@composepointsbody{\exf at problem@pointsshow}}%
+    \global\let\exf at problem@pointsshow\@undefined%
+   \fi%
+  \fi\fi}
+
+\newlength{\exf at solution@points at dim}
+
+\newcommand{\exf at awardpointsalt}[2][]{%
+  \exf at ensuretext{\exf at config@composepointsawardalt{#2}{#1}}}
+\newcommand{\exf at awardpointsreg}[2][]{%
+  \global\addtolength{\exf at solution@points at dim}{#2 pt}%
+  \exf at ensuretext{\exf at config@composepointsaward{#2}{#1}}}
+\newcommand{\awardpoints}{\@ifstar\exf at awardpointsalt\exf at awardpointsreg}
+
+\define at key{exf at sheet}{points}{\def\exf at points@given{#1}}
+\define at key{exf at sheet}{number}{\setcounter{\exf at sheetcounter}{#1}}
+\define at key{exf at sheet}{label}{\def\exf at label{#1}}
+\define at key{exf at sheet}{tag}{\def\sheettag{#1}}
+
+\newenvironment{\exf at sheetname}[1][]{%
+  \exf at config@insertsheetclearpage%
+  \refstepcounter{\exf at sheetcounter}%
+  \ifexf at style@sheetequation%
+   \exf at eqsav\value{equation}%
+   \setcounter{equation}{\value{exf at sheetequation}}%
+   \let\theequation\theexf at sheetequation%
+   \let\theHequation\theHexf at sheetequation%
+  \fi%
+  \let\exf at points@given\@undefined%
+  \def\sheettag{\csname the\exf at sheetcounter\endcsname}%
+  \setlength{\exf at sheet@points at dim}{0pt}%
+  \let\exf at label\@undefined%
+  \setkeys{exf at sheet}{#1}%
+  \ifexf at autolabelsheet\label{\exf at config@labelsheet{\sheettag}}\fi%
+  \ifdefined\exf at label\label{\exf at label}\fi%
+  \ifdefined\exf at points@given%
+   \let\exf at data@sheet at rawpoints\exf at points@given%
+  \else\ifcsname exf at sheetpoints@\sheettag\endcsname%
+   \exf at csdotwo\let\exf at data@sheet at rawpoints{exf at sheetpoints@\sheettag}%
+  \fi\fi%
+  \def\exf at tmp{sheet}\ifx\exf at metadata\exf at tmp%
+   \exf at writemetadata{sheet}\fi%
+  \exf at config@insertsheetbefore%
+  \ifx\exf at config@toclevelsheet\exf at empty\else%
+   \ifdefined\phantomsection\phantomsection\fi\fi%
+  \exf at addcontentsline{\exf at config@toclevelsheet}%
+   {\exf at config@composetocsheet{\csname the\exf at sheetcounter\endcsname}%
+    {\exf at data@sheet at rawtitle}}%
+  \exf at config@insertsheettitle}%
+ {\ifdefined\exf at points@given%
+   \ifdim\exf at sheet@points at dim=0pt\else%
+    \ifdim\exf at sheet@points at dim=\exf at data@sheet at rawpoints pt\else%
+     \PackageWarning{exframe}{points mismatch for %
+      \exf at sheetname\space\csname the\exf at sheetcounter\endcsname}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at sheetname}%
+      {\strip at pt\exf at sheet@points at dim}{\exf at data@sheet at rawpoints}\fi%
+   \fi\fi%
+  \else%
+   \ifx\exf at data@sheet at rawpoints\exf at empty\else%
+    \ifdim\exf at sheet@points at dim=\exf at data@sheet at rawpoints pt\else%
+     \PackageWarning{exframe}{points changed for %
+      \exf at sheetname\space\csname the\exf at sheetcounter\endcsname;
+      rerun to fix}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at sheetname}%
+      {\strip at pt\exf at sheet@points at dim}{\exf at data@sheet at rawpoints}\fi%
+   \fi\fi%
+   \ifdim\exf at sheet@points at dim=0pt%
+    \def\exf at data@sheet at rawpoints{}%
+   \else%
+    \edef\exf at data@sheet at rawpoints{\strip at pt\exf at sheet@points at dim}%
+   \fi%
+  \fi%
+  \ifx\exf at data@sheet at rawpoints\exf at empty\else%
+   \exf at writesheetpoints{\exf at data@sheet at rawpoints}%
+  \fi%
+  \exf at solbelowis{sheet}{\insertsolutions}%
+  \exf at config@insertsheetafter%
+  \exf at config@insertsheetclearpage%
+  \ifexf at style@sheetequation%
+   \setcounter{exf at sheetequation}{\value{equation}}%
+   \setcounter{equation}{\exf at eqsav}%
+  \fi%
+  \ignorespacesafterend}
+
+\newcommand{\exercisecleardoublepage}{%
+  \clearpage\ifexf at twoside\ifodd\value{page}\else%
+  \thispagestyle{empty}\hbox{}\newpage\fi\fi}
+
+\newif\ifexf at problem@solnewsec\exf at problem@solnewsectrue
+
+\define at key{exf at problem}{points}{\def\exf at points@given{#1}}
+\define at key{exf at problem}{label}{\def\exf at label{#1}}
+\define at key{exf at problem}{tag}{\def\problemtag{#1}}
+\define at key{exf at problem}{sollabel}{\xdef\exf at sollabel{#1}}
+
+\newenvironment{\exf at problemname}[1][]{%
+  \par\exf at config@styletext%
+  \addvspace{\exf at config@skipproblemabove}%
+  \refstepcounter{\exf at problemcounter}%
+  \exf at config@insertproblembefore%
+  \global\exf at problem@solnewsectrue%
+  \ifexf at style@problemequation%
+   \exf at eqsav\value{equation}%
+   \setcounter{equation}{\value{exf at problemequation}}%
+   \let\theequation\theexf at problemequation%
+   \let\theHequation\theHexf at problemequation%
+  \fi%
+  \begingroup%
+  \def\exf at in@problem{}%
+  \exf at init@intro{\exf at config@skipprobleminfo}%
+  \def\problemtag{\csname the\exf at problemcounter\endcsname}%
+  \let\exf at points@given\@undefined%
+  \let\exf at label\@undefined%
+  \global\let\exf at sollabel\@undefined%
+  \setlength{\exf at problem@points at dim}{0pt}%
+  \setkeys{exf at problem,exf at probleminfo}{#1}%
+  \ifexf at autolabelproblem\label{\exf at config@labelproblem{\problemtag}}\fi%
+  \ifdefined\exf at label\label{\exf at label}\fi%
+  \xdef\exf at prevprob{\csname the\exf at problemcounter\endcsname}%
+  \ifcsname theH\exf at problemcounter\endcsname%
+   \xdef\exf at prevprobhref{\exf at problemcounter.%
+    \csname theH\exf at problemcounter\endcsname}%
+  \fi%
+  \ifx\exf at data@problem at rawtitle\exf at empty%
+    \global\let\exf at prevprobtitle\@undefined%
+  \else%
+    \xdef\exf at prevprobtitle{\exf at data@problem at rawtitle}\fi%
+  \global\let\exf at prevsubprob\@undefined%
+  \global\let\exf at prevsubprobhref\@undefined%
+  \let\exf at problem@points\@undefined%
+  \ifdefined\exf at points@given%
+   \let\exf at problem@points\exf at points@given%
+  \else%
+   \ifcsname exf at problempoints@\problemtag\endcsname%
+    \exf at csdotwo\let\exf at problem@points{exf at problempoints@\problemtag}%
+  \fi\fi%
+  \global\let\exf at prevpoints\exf at problem@points%
+  \let\exf at problem@pointsshow\@undefined%
+  \ifdefined\exf at problem@points\ifdim\exf at problem@points pt=0pt\else%
+   \let\exf at problem@pointsshow\exf at problem@points%
+  \fi\fi%
+  \exf at pointsatis{off}{\let\exf at problem@pointsshow\@undefined}%
+  \exf at pointsatis{start}{\ifdefined\exf at problem@pointsshow%
+   \exf at exptwo\exf at append@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at problem@pointsshow}}%
+   \let\exf at problem@pointsshow\@undefined\fi}%
+  \exf at pointsatis{start*}{\ifdefined\exf at problem@pointsshow%
+   \exf at exptwo\exf at prepend@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at problem@pointsshow}}%
+   \let\exf at problem@pointsshow\@undefined\fi}%
+  \exf at config@insertprobleminfo%
+  \exf at config@styletextproblem%
+  \ifdim\exf at config@skipproblemitem=0pt%
+   \exf at prepend@intro{{%
+    \exf at config@styletitle\exf at config@styletitleproblem%
+    \exf at config@composetitleproblem{\csname the\exf at problemcounter\endcsname}%
+     {\exf at data@problem at rawtitle}}}%
+  \else%
+   \ifdim\exf at config@skipproblemitem>0pt%
+    \setlength\exf at tmpdim{\exf at config@skipproblemitem}%
+   \else%
+    \settowidth\exf at tmpdim{%
+     \exf at config@styletitle\exf at config@styletitleproblem%
+     \exf at config@composeitemproblem{\exf at config@counterproblemmax}%
+     \exf at config@composeitemproblemsep}%
+   \fi%
+   \advance\leftskip\exf at tmpdim%
+   \advance\linewidth -\exf at tmpdim%
+   \advance\@totalleftmargin\exf at tmpdim%
+   \def\exf at introitem{\makebox[0cm][r]{%
+    \exf at config@styletitle\exf at config@styletitleproblem%
+    \exf at config@composeitemproblem{\csname the\exf at problemcounter\endcsname}%
+     \exf at config@composeitemproblemsep}}%
+   \ifx\exf at data@problem at rawtitle\exf at empty\else%
+    \exf at prepend@intro{{%
+     \exf at config@styletitle\exf at config@styletitleproblem%
+     \exf at config@composetitleproblem{\exf at empty}{\exf at data@problem at rawtitle}}}%
+   \fi%
+  \fi%
+  \exf at pointsatis{margin}{\ifdefined\exf at problem@pointsshow%
+   \expandafter\exf at prepend@def\expandafter\exf at intro\expandafter%
+    {\expandafter\protect\expandafter%
+     \exf at config@insertpointsmargin\expandafter{\expandafter%
+      \exf at config@composepointsmargin\expandafter{\exf at problem@pointsshow}}}%
+   \let\exf at problem@pointsshow\@undefined\fi}%
+  \exf at write@intro{\exf at config@skipproblemtitle}%
+  \exf at addcontentsline{\exf at config@toclevelproblem}%
+   {\exf at config@composetocproblem{\csname the\exf at problemcounter\endcsname}%
+    {\exf at data@problem at rawtitle}}%
+  \@afterindentfalse}%
+ {\exf at pointsatis{end}{\showpoints}%
+  \ifdefined\exf at points@given%
+   \ifdim\exf at problem@points at dim=0pt\else%
+    \ifdim\exf at problem@points at dim=\exf at problem@points pt\else%
+     \PackageWarning{exframe}{points mismatch for %
+      \exf at problemname\space\csname the\exf at problemcounter\endcsname}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at problemname}%
+      {\strip at pt\exf at problem@points at dim}{\exf at problem@points}\fi%
+   \fi\fi%
+  \else%
+   \ifdefined\exf at problem@points%
+    \ifdim\exf at problem@points at dim=\exf at problem@points pt\else%
+     \PackageWarning{exframe}{points changed for %
+      \exf at problemname\space\csname the\exf at problemcounter\endcsname;
+      rerun to fix}%
+     \ifexf at warntext\exf at config@insertwarnpoints{\exf at problemname}%
+      {\strip at pt\exf at problem@points at dim}{\exf at problem@points}\fi%
+   \fi\fi%
+   \ifdim\exf at problem@points at dim=0pt%
+    \let\exf at problem@points\@undefined%
+   \else%
+    \edef\exf at problem@points{\strip at pt\exf at problem@points at dim}%
+   \fi%
+  \fi%
+  \ifdefined\exf at problem@points%
+   \exf at writeproblempoints{\exf at problem@points}%
+   \global\addtolength{\exf at sheet@points at dim}{\exf at problem@points pt}%
+  \fi%
+  \ifdefined\exf at problem@points\else\ifdim\exf at sheet@points at dim=0pt\else%
+   \PackageWarning{exframe}{no points defined for \exf at problemname}%
+  \fi\fi%
+  \par\endgroup%
+  \exf at config@insertproblemafter%
+  \addvspace{\exf at config@skipproblembelow}%
+  \exf at solbelowis{problem}{%
+   \exf at showsolutions{\exf at config@composetitlesolutionmulti}{}}%
+  \global\let\exf at prevsubprob\@undefined%
+  \global\let\exf at prevsubprobhref\@undefined%
+  \ifexf at style@problemequation%
+   \setcounter{exf at problemequation}{\value{equation}}%
+   \setcounter{equation}{\exf at eqsav}%
+  \fi%
+  \ignorespacesafterend}
+
+\define at key{exf at subproblem}{points}{\def\exf at subproblem@points{#1}}
+\define at key{exf at subproblem}{label}{\def\exf at label{#1}}
+
+\newenvironment{\exf at subproblemname}[1][]{%
+  \par%
+  {\exf at config@styletext\addvspace{\exf at config@skipsubproblemabove}}%
+  \refstepcounter{\exf at subproblemcounter}%
+  \exf at config@insertsubproblembefore%
+  \xdef\exf at prevsubprob{\csname the\exf at subproblemcounter\endcsname}%
+  \ifcsname theH\exf at subproblemcounter\endcsname%
+   \xdef\exf at prevsubprobhref{\exf at subproblemcounter.%
+    \csname theH\exf at subproblemcounter\endcsname}%
+  \fi%
+  \begingroup%
+  \def\exf at in@subproblem{}%
+  \exf at init@intro{\exf at config@skipsubprobleminfo}%
+  \let\exf at subproblem@points\@undefined%
+  \let\exf at label\@undefined%
+  \setkeys{exf at subproblem,exf at probleminfo}{#1}%
+  \ifdefined\exf at label\label{\exf at label}\fi%
+  \ifdefined\exf at subproblem@points%
+   \global\let\exf at prevpoints\exf at subproblem@points%
+   \global\addtolength{\exf at problem@points at dim}{\exf at subproblem@points pt}%
+  \else%
+   \ifdim\exf at problem@points at dim=0pt\else%
+    \PackageWarning{exframe}{no points defined for \exf at subproblemname}%
+   \fi%
+  \fi%
+  \exf at subpointsatis{off}{\let\exf at subproblem@points\@undefined}%
+  \exf at subpointsatis{start}{\ifdefined\exf at subproblem@points%
+   \exf at exptwo\exf at append@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at subproblem@points}}%
+   \let\exf at subproblem@points\@undefined\fi}%
+  \exf at subpointsatis{start*}{\ifdefined\exf at subproblem@points%
+   \exf at exptwo\exf at prepend@intro{\expandafter%
+    \exf at config@composepointsstart\expandafter{\exf at subproblem@points}}%
+   \let\exf at subproblem@points\@undefined\fi}%
+  \exf at config@insertsubprobleminfo%
+  \ifdim\exf at config@skipsubproblemitem=0pt%
+   \exf at prepend@intro{{%
+    \exf at config@styletitle\exf at config@styletitlesubproblem%
+    \exf at config@composetitlesubproblem{%
+     \csname the\exf at subproblemcounter\endcsname}}}%
+  \else%
+   \ifdim\exf at config@skipsubproblemitem>0pt%
+    \setlength\exf at tmpdim{\exf at config@skipsubproblemitem}%
+   \else%
+    \settowidth\exf at tmpdim{%
+     \exf at config@styletitle\exf at config@styletitlesubproblem%
+     \exf at config@composeitemsubproblem{\exf at config@countersubproblemmax}%
+     \exf at config@composeitemsubproblemsep}%
+   \fi%
+   \advance\leftskip\exf at tmpdim%
+   \advance\linewidth -\exf at tmpdim%
+   \advance\@totalleftmargin\exf at tmpdim%
+   \def\exf at introitem{\makebox[0cm][r]{%
+    \exf at config@styletitle\exf at config@styletitlesubproblem%
+    \exf at config@composeitemsubproblem%
+     {\csname the\exf at subproblemcounter\endcsname}%
+    \exf at config@composeitemsubproblemsep}}%
+  \fi%
+  \exf at subpointsatis{margin}{\ifdefined\exf at subproblem@points%
+   \expandafter\exf at prepend@def\expandafter\exf at intro\expandafter%
+    {\expandafter\protect\expandafter%
+     \exf at config@insertpointsmargin\expandafter{\expandafter%
+      \exf at config@composepointsmargin\expandafter{\exf at subproblem@points}}}%
+   \let\exf at subproblem@points\@undefined\fi}%
+  \exf at write@intro{\exf at config@skipsubproblemtitle}%
+  \@afterindentfalse}%
+ {\exf at subpointsatis{end}{\showpoints}%
+  \par\endgroup%
+  {\exf at config@styletext\addvspace{\exf at config@skipsubproblembelow}}%
+  \exf at config@insertsubproblemafter%
+  \exf at solbelowis{subproblem}{\exf at showsolutions%
+   {\exf at config@composetitlesolutionsingle}{}}%
+  \ignorespacesafterend}
+
+\define at key{exf at solution}{prob}{\def\exf at solprob{#1}}
+\define at key{exf at solution}{subprob}{\def\exf at solsubprob{#1}}
+\define at key{exf at solution}{problemtag}{\def\problemtag{#1}}
+\define at key{exf at solution}{sheettag}{\def\sheettag{#1}}
+\define at key{exf at solution}{href}{\def\exf at solhref{#1}}
+\define at key{exf at solution}{label}{\def\exf at label{#1}}
+\define at key{exf at solution}{points}{\def\exf at solution@points{#1}}
+\define at key{exf at solution}{probtitle}{\def\exf at solprobtitle{#1}}
+
+\newenvironment{printsolution}[1]{%
+  \par%
+  {\exf at config@styletext\addvspace{\exf at config@skipsolutionabove}}%
+  \exf at config@insertsolutionbefore%
+  \ifexf at style@solutionequation%
+   \exf at eqsav\value{equation}%
+   \setcounter{equation}{\value{exf at solutionequation}}%
+   \let\theequation\theexf at solutionequation%
+   \let\theHequation\theHexf at solutionequation%
+  \fi%
+  \begingroup%
+  \def\exf at solprob{}%
+  \def\exf at solsubprob{}%
+  \let\exf at label\@undefined%
+  \setlength{\exf at solution@points at dim}{0pt}%
+  \def\exf at solhref{}%
+  \exf at init@intro{\exf at config@skipsolutioninfo}%
+  \setkeys{exf at solution,exf at probleminfo}{#1}%
+  \exf at csdo\def{the\exf at solutioncounter}%
+   {\exf at config@composeitemsolution{\exf at solprob}{\exf at solsubprob}}%
+  \refstepcounter{\exf at solutioncounter}%
+  \ifdefined\exf at label\label{\exf at label}\fi%
+  \exf at config@insertsolutioninfo%
+  \exf at config@styletext\exf at config@styletextsolution%
+  \ifx\exf at solsubprob\exf at empty%
+   \let\exf at tmp\exf at config@skipsolutionitem%
+  \else%
+   \let\exf at tmp\exf at config@skipsolutionitemsub%
+  \fi%
+  \ifdim\exf at tmp=0pt%
+   \protected at edef\exf at solution@title{%
+    \exf at composetitle{\exf at solprob}{\exf at solsubprob}}%
+   \ifx\exf at solution@title\exf at empty\else%
+    \exf at prepend@intro{{%
+     \exf at config@styletitle\exf at config@styletitlesolution%
+     \ifexf at solutionhref\exf at href{\exf at solhref}%
+      {\exf at solution@title}\else\exf at solution@title\fi}}%
+   \fi%
+  \else%
+   \ifdim\exf at tmp>0pt%
+    \setlength\exf at tmpdim{\exf at tmp}%
+   \else%
+    \settowidth\exf at tmpdim{%
+     \exf at config@styletitle\exf at config@styletitlesolution%
+     \ifx\exf at solsubprob\exf at empty%
+      \exf at config@composeitemsolution{\exf at config@counterproblemmax}%
+       {\exf at config@countersubproblemmax}%
+     \else%
+      \exf at config@composeitemsolutionsub{\exf at config@counterproblemmax}%
+       {\exf at config@countersubproblemmax}%
+     \fi\exf at config@composeitemsolutionsep}%
+   \fi%
+   \advance\leftskip\exf at tmpdim%
+   \advance\linewidth -\exf at tmpdim%
+   \advance\@totalleftmargin\exf at tmpdim%
+   \ifx\exf at solsubprob\exf at empty%
+    \protected at edef\exf at solution@item%
+     {\exf at config@composeitemsolution{\exf at solprob}{\exf at empty}}%
+   \else%
+    \protected at edef\exf at solution@item%
+     {\exf at config@composeitemsolutionsub{\exf at solprob}{\exf at solsubprob}}%
+   \fi%
+   \def\exf at introitem{\makebox[0cm][r]{%
+    \exf at config@styletitle\exf at config@styletitlesubproblem%
+    \ifexf at solutionhref\exf at href{\exf at solhref}{\exf at solution@item}%
+    \else\exf at solution@item\fi%
+    \exf at config@composeitemproblemsep}}%
+  \fi%
+  \exf at write@intro{\exf at config@skipsolutiontitle}%
+  \@afterindentfalse}%
+ {\ifdefined\exf at solution@points\ifdim\exf at solution@points at dim=0pt\else%
+   \ifdim\exf at solution@points at dim=\exf at solution@points pt\else%
+    \PackageWarning{exframe}{points mismatch in \exf at solutionname}%
+    \ifexf at warntext\exf at config@insertwarnpoints{\exf at solutionname}%
+     {\strip at pt\exf at solution@points at dim}{\exf at solution@points}\fi%
+  \fi\fi\fi%
+  \par\endgroup%
+  {\exf at config@styletext\addvspace{\exf at config@skipsolutionbelow}}%
+  \exf at config@insertsolutionafter%
+  \ifexf at style@solutionequation%
+   \setcounter{exf at solutionequation}{\value{equation}}%
+   \setcounter{equation}{\exf at eqsav}%
+  \fi%
+  \ignorespacesafterend}
+
+\newcommand{\solutionssection}[1]{\begingroup%
+  \def\exf at solprob{}%
+  \def\exf at solsubprob{}%
+  \def\exf at solprobtitle{}%
+  \let\exf at label\@undefined%
+  \let\exf at solhref\@undefined%
+  \setkeys{exf at solution}{#1}%
+  \let\exf at composetitle\exf at config@composetitlesolutionsproblemmulti%
+  \def\exf at solutionstoc{\exf at addcontentsline{\exf at config@toclevelsolution}%
+    {\exf at config@composetocsolution{\exf at solprob}{\exf at solprobtitle}}}%
+  \exf at solbelowis{problem}{\let\exf at composetitle%
+    \exf at config@composetitlesolutionsproblemsingle}%
+  \exf at solutionssection{\exf at config@styletitlesolutionsproblem}%
+   {\exf at composetitle{\exf at solprob}{\exf at solprobtitle}}%
+   {\exf at config@skipsolutionsproblem}%
+   {\exf at solutionstoc}{\exf at label}{\exf at solhref}%
+  \endgroup}
+
+\newenvironment{\exf at solutionname}%
+  {\exf at scanblock{\exf at scansolution}}{\endexf at scansolution}%
+
+\newenvironment{exf at scansolution}[2]{%
+  \exf at solbelowis{here}{\showpoints}%
+  \global\exf at bufcleanfalse%
+  \ifexf at problem@solnewsec%
+   \def\exf at probarg{\ifdefined\exf at prevprob prob={\exf at prevprob}\fi%
+    \ifdefined\exf at prevprobtitle,probtitle={\exf at prevprobtitle}\fi%
+    \ifdefined\exf at prevprobhref,href={\exf at prevprobhref}\fi%
+    \ifdefined\exf at sollabel,label={\exf at sollabel}\fi}%
+   \exf at solbelowis{here}{\let\exf at probarg\@undefined}%
+   \exf at solbelowis{subproblem}{\let\exf at probarg\@undefined}%
+   \ifdefined\exf at probarg%
+    \ifexf at lineno\exf at addbufline{\exf at linesep}\exf at addbufline{\exf at lineno}\fi%
+    \exf at addbufline{\@backslashchar solutionssection{\exf at probarg}}%
+    \exf at addbufline{}%
+   \fi%
+   \global\exf at problem@solnewsecfalse%
+  \fi%
+  \ifexf at lineno\exf at addbufline{\exf at linesep}\exf at addbufline{\exf at lineno}\fi%
+  \def\exf at subprobarg{%
+    \ifdefined\exf at prevprob prob={\exf at prevprob},\fi%
+    \ifdefined\exf at prevsubprob%
+     subprob={\exf at prevsubprob},%
+     \ifdefined\exf at prevsubprobhref href={\exf at prevsubprobhref},\fi%
+    \else%
+     \ifdefined\exf at prevprobhref href={\exf at prevprobhref},\fi%
+    \fi%
+    \ifdefined\exf at prevpoints points={\exf at prevpoints},\fi%
+    \ifdefined\sheettag sheettag={\sheettag},\fi%
+    \ifdefined\problemtag problemtag={\problemtag},\fi}%
+  \exf at addbufline{\@backslashchar begin{printsolution}{\exf at subprobarg#1}}%
+  \global\let\exf at prevsubprob\@undefined%
+  \global\let\exf at prevsubprobhref\@undefined%
+  \global\let\exf at prevpoints\@undefined%
+  \exf at verbatim#2}%
+ {\exf at endverbatim%
+  \exf at addbufline{\@backslashchar end{printsolution}}%
+  \ifexf at infile%
+   \exf at writebuf%
+   \exf at clearbuf%
+  \fi%
+  \ifsolutions\else\exf at clearbuf\fi%
+  \exf at solbelowis{here}{\exf at showsolutions%
+   {\exf at config@composetitlesolutionsingle}{}}%
+  \exf at solbelowis{subproblem}{\ifdefined\exf at in@subproblem\else%
+   \exf at showsolutions{\exf at config@composetitlesolutionsingle}{}\fi}%
+  \exf at solbelowis{problem}{\ifdefined\exf at in@problem\else%
+   \exf at showsolutions{\exf at config@composetitlesolutionmulti}{}\fi}%
+  \ignorespacesafterend}
+
+\newcommand{\exf at solutionssection}[6]{%
+  \protected at edef\exf at solutionstitleexp{#2}%
+  \ifx\exf at solutionstitleexp\exf at empty\else%
+   \ifdefined#5%
+    \exf at csdo\def{the\exf at solutioncounter}%
+     {\exf at config@composeitemsolution{\exf at solprob}{\exf at solsubprob}}%
+    \refstepcounter{\exf at solutioncounter}\label{#5}%
+   \fi%
+   \exf at section{#3}{\exf at config@styletitle\exf at config@styletitlesolution#1%
+    \ifexf at solutionhref\exf at href{#6}{\exf at solutionstitleexp}%
+    \else\exf at solutionstitleexp\fi}#4%
+  \fi}
+
+\newcommand{\exf at solutionstitle}{\exf at solutionssection%
+  {\exf at config@styletitlesolutions}{%
+   \exf at config@composetitlesolutions}{\exf at config@skipsolutionstitle}%
+   {\exf at addcontentsline{\exf at config@toclevelsolutions}%
+    {\exf at config@composetocsolutions}}{\@undefined}{\@undefined}}
+
+\newcommand{\exf at showsolutions}[2]{%
+  \ifexf at bufclean\else\begingroup%
+   \par\exf at config@styletext\addvspace{\exf at config@skipsolutionsabove}%
+   \exf at config@styletextsolution%
+   \exf at config@insertsolutionsbefore%
+   \let\exf at composetitle#1%
+   #2%
+   \exf at sourcebuf%
+   \exf at clearbuf%
+   \removelastskip%
+   \exf at config@insertsolutionsafter%
+   \par\exf at config@styletext\addvspace{\exf at config@skipsolutionbelow}%
+  \endgroup\fi}
+
+\newcommand{\writesolutions}[1][\jobname]{\exf at closefile\exf at startfile{#1}}
+
+\newcommand{\closesolutions}{\exf at closefile}
+
+\newcommand{\readsolutions}[1][\jobname]{\exf at closefile%
+  \ifsolutions\begingroup%
+   \exf at config@styletext\exf at config@styletextsolution%
+   \let\exf at config@composetitlesolution\exf at config@composetitlesolutionmulti%
+   \exf at solutionstitle%
+   \input{#1.sol}%
+  \endgroup\fi}
+
+\newcommand{\insertsolutions}{\exf at showsolutions%
+  {\exf at config@composetitlesolutionmulti}{\exf at solutionstitle}}
+
+\endinput
+%%
+%% End of file `exframe.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2019-01-16 18:58:39 UTC (rev 49726)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2019-01-16 22:21:34 UTC (rev 49727)
@@ -263,7 +263,7 @@
     everyhook everypage
     exam exam-n exam-randomizechoices examdesign example examplep
     exceltex excludeonly exercise exercisebank exercisepoints exercises
-    exp-testopt
+    exframe exp-testopt
     expdlist expex export expressg exsheets exsol extarrows exteps
     extpfeil extract extsizes
   facsimile factura facture facture-belge-simple-sans-tva faktor
@@ -563,7 +563,7 @@
     pxchfon pxcjkcat pxfonts pxgreeks pxjahyper
     pxpgfmark pxrubrica pxtatescale pxtxalfa pxufont
     pygmentex python pythonhighlight pythontex
-  qcircuit qcm qobitree qrcode qstest qsymbols qtree
+  qcircuit qcm qobitree qrcode qsharp qstest qsymbols qtree
      quantikz quattrocento quicktype quotchap quoting quotmark quran quran-de
   r_und_s raleway ran_toks randbild randomlist randomwalk randtext
     rank-2-roots rccol rcs rcs-multi rcsinfo

Modified: trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2019-01-16 18:58:39 UTC (rev 49726)
+++ trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2019-01-16 22:21:34 UTC (rev 49727)
@@ -386,6 +386,7 @@
 depend exam-n
 depend exam-randomizechoices
 depend examdesign
+depend exframe
 depend example
 depend examplep
 depend exceltex

Added: trunk/Master/tlpkg/tlpsrc/exframe.tlpsrc
===================================================================


More information about the tex-live-commits mailing list