texlive[51388] Master/texmf-dist: exframe (16jun19)

commits+karl at tug.org commits+karl at tug.org
Mon Jun 17 00:04:42 CEST 2019


Revision: 51388
          http://tug.org/svn/texlive?view=revision&revision=51388
Author:   karl
Date:     2019-06-17 00:04:41 +0200 (Mon, 17 Jun 2019)
Log Message:
-----------
exframe (16jun19)

Modified Paths:
--------------
    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/exfsamp.tex
    trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex
    trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx
    trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty

Modified: trunk/Master/texmf-dist/doc/latex/exframe/README.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/README.txt	2019-06-16 22:04:20 UTC (rev 51387)
+++ trunk/Master/texmf-dist/doc/latex/exframe/README.txt	2019-06-16 22:04:41 UTC (rev 51388)
@@ -1,4 +1,4 @@
-exframe v3.2
+exframe v3.3
 Copyright 2011-2019 Niklas Beisert
 
 exframe is a LaTeX2e package which provides a general purpose

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exframe.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfsamp.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfsamp.tex	2019-06-16 22:04:20 UTC (rev 51387)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfsamp.tex	2019-06-16 22:04:41 UTC (rev 51388)
@@ -17,7 +17,7 @@
 %% version 2005/12/01 or later.
 %% 
 \NeedsTeXFormat{LaTeX2e}[1996/12/01]
-\ProvidesFile{exfsamp.tex}[2019/05/01 v3.2 standalone sample for exframe]
+\ProvidesFile{exfsamp.tex}[2019/06/15 v3.3 standalone sample for exframe]
 \documentclass[12pt]{article}
 
 \usepackage{geometry}
@@ -41,10 +41,15 @@
 \exerciseconfig{countersubproblem}{\roman{subproblem})}
 \exerciseconfig{countersubproblemmax}{vii)}
 
+\exerciseconfig{insertsubprobleminfo}{%
+ \switchpoints{}{\addprobleminfo*{%
+   \hspace{-\getexerciseconfig{skipsubprobleminfo}}*}}%
+  {}{}{\getsubproblempoints{}}}
+
 \exerciseconfig{termsheet}{\"Ubungsblatt}
 \exerciseconfig{termsheets}{\"Ubungsbl\"atter}
 
-\exercisestyle{pointsat=margin}
+\exercisestyle{problempointsat=margin}
 \reversemarginpar
 \exerciseconfig{composepointsmargin}[1]{#1p.}
 \exerciseconfig{composepointspairmargin}[2]{

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex	2019-06-16 22:04:20 UTC (rev 51387)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex	2019-06-16 22:04:41 UTC (rev 51388)
@@ -17,7 +17,7 @@
 %% version 2005/12/01 or later.
 %% 
 \NeedsTeXFormat{LaTeX2e}[1996/12/01]
-\ProvidesFile{exfserm.tex}[2019/05/01 v3.2 multipart sample for exframe]
+\ProvidesFile{exfserm.tex}[2019/06/15 v3.3 multipart sample for exframe]
 \input{childdoc.def}
 \childdocmain{exfserm}
 

Modified: trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx	2019-06-16 22:04:20 UTC (rev 51387)
+++ trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx	2019-06-16 22:04:41 UTC (rev 51388)
@@ -20,11 +20,11 @@
 % exfserpe.tex, exfserpf.tex, exfsermk.sh, exfsermk.mak.
 %
 %<package|samplesingle|samplemultimain>\NeedsTeXFormat{LaTeX2e}[1996/12/01]
-%<package>\ProvidesPackage{exframe}[2019/05/01 v3.2 Framework for Exercise Problems]
-%<samplesingle>\ProvidesFile{exfsamp.tex}[2019/05/01 v3.2 standalone sample for exframe]
-%<samplemultimain>\ProvidesFile{exfserm.tex}[2019/05/01 v3.2 multipart sample for exframe]
+%<package>\ProvidesPackage{exframe}[2019/06/15 v3.3 Framework for Exercise Problems]
+%<samplesingle>\ProvidesFile{exfsamp.tex}[2019/06/15 v3.3 standalone sample for exframe]
+%<samplemultimain>\ProvidesFile{exfserm.tex}[2019/06/15 v3.3 multipart sample for exframe]
 %<*driver>
-\def\thedate#1{2019/05/01}\def\theversion#1{v3.2}
+\def\thedate#1{2019/06/15}\def\theversion#1{v3.3}
 \ProvidesFile{exframe.dtx}[\thedate{} \theversion{} exframe reference manual file]
 \PassOptionsToClass{10pt,a4paper}{article}
 \documentclass{ltxdoc}
@@ -218,7 +218,7 @@
 \end{tabular}
 \end{center}
 %
-A |subproblem| block must be contained within a |problem| block
+A |subproblem| environment must be contained within a |problem| environment
 (however, a |problem| block need not contain |subproblem| blocks).
 
 \DescribeEnv{solution}
@@ -232,13 +232,14 @@
 \end{tabular}
 \end{center}
 %
-A |solution| block should be at the end of a |subproblem| or |problem| block
+A |solution| environment should be
+at the end of a |subproblem| or |problem| environment
 (it is not mandatory to provide a |solution|).
-It can be contained within the corresponding block or it can follow it.
+It can be contained within the corresponding environment 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;
+to define a solution \emph{within} the corresponding environment;
 this may also have some technical advantages and produce
 a slightly better result in terms of layout.
 
@@ -259,10 +260,11 @@
 A header will be added to the sheet according to the specified layout.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\subsection{Solution Display}
+\subsection{Solution and Problem Display}
 \label{sec:solutions}
 
-There are several options to control the output of solutions.
+There are several options to control the output of solutions
+and of problems.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \DescribeMacro{solutions}
@@ -327,15 +329,11 @@
 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
-does not inherit the margin of the parent block.
-The alternate mode |here*| does not intermediately store
-the solution block content in a token buffer;
-this might resolve some tokenisation issues
-in special circumstances.
+does not inherit the margin of the parent environment.
 The alternate modes |problem*| and |subproblem*|
-positions the solution \emph{after} the (sub)problem block
+positions the solution \emph{after} the (sub)problem environment
 such that it does not inherit any layout,
-but also no definitions made in the parent block.
+but also no definitions made in the parent environment.
 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
@@ -352,7 +350,8 @@
 \end{center}
 %
 The optional argument describes the filename as \textit{filename}|.sol|;
-no argument defaults to the main tex filename as |\jobname.sol|.
+no argument defaults to the main tex filename as |\jobname.sol|;
+the extension |.sol| can be customised by the configuration |extsolutions|.
 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
@@ -372,6 +371,94 @@
 This command outputs a sectional title
 and reads the file via |\input{|\textit{filename}|.sol}|.
 
+\medskip
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutionbuf}
+\DescribeMacro{problembuf}
+The package offers similar functionality to control the display of problems.
+In order to have any control over the content of |problem| environments,
+the latter needs to be read into an internal buffer.
+Reading of solutions and problems to internal buffers is activated
+or deactivated by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exercisesetup{solutionbuf|[|=true|\textbar|false|]|}|\\
+|\exercisesetup{problembuf|[|=true|\textbar|false|]|}|
+\end{tabular}
+\end{center}
+%
+By default, |solution| environments are read to an internal buffer,
+while the content of |problem| environments is processed directly
+by the \TeX\ engine.
+Therefore, the following options to control the display
+of |problem| environments require the statement |\exercisesetup{problembuf}|.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{problemmanual}
+\DescribeMacro{\insertproblems}
+The immediate display of |problem| environments is controlled by:
+%
+\begin{center}
+|\exercisestyle{problemmanual|[|=true|\textbar|false|]|}|
+\end{center}
+%
+In the default automatic mode, problems are displayed directly
+where they are declared.
+In manual mode, problems are collected to an internal buffer,
+and only displayed by issuing |\insertproblems|.
+
+Note that |solution| environments should be
+declared within the corresponding |problem| environment in order to
+preserve their appropriate association.
+The |solution| environment is then processed at the place
+where the |problem| environment is displayed,
+and it may (or may not) be deferred further.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\writeproblems}
+\DescribeMacro{\readproblems}
+Problems can be written out to an external file for later usage.
+The functionality is analogous to solutions
+and uses the macros:
+%
+\begin{center}
+\begin{tabular}{l}
+|\writeproblems[|\textit{filename}|]|\\
+|\readproblems[|\textit{filename}|]|
+\end{tabular}
+\end{center}
+%
+The optional argument describes the filename as \textit{filename}|.prb|;
+no argument defaults to the main tex filename as |\jobname.prb|;
+the extension |.prb| can be customised by the configuration |extproblems|.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{disable}
+\DescribeMacro{insertproblemselect}
+The display of a particular |problem|
+can be suppressed altogether by an optional argument:
+%
+\begin{center}
+|\begin{problem}[disable]|
+\end{center}
+%
+
+This option can be exploited to automatically
+suppress certain classes of problems as follows:
+A hook function |insertproblemselect| declared by:
+%
+\begin{center}
+|\exerciseconfig{insertproblemselect}[1]{|\textit{code}|}|
+\end{center}
+%
+can call
+|\setproblemdata{disable}| whenever a problem is to be suppressed.
+In order to decide, the optional argument of the |problem| environment
+is passed on to the hook function as the single argument.
+Note that the argument needs to be processed manually.
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \subsection{Metadata}
 \label{sec:metadata}
@@ -477,8 +564,10 @@
 for sheets and problems:
 %
 \begin{center}
-|\begin{sheet}[|\textit{opts}|]|
+\begin{tabular}{l}
+|\begin{sheet}[|\textit{opts}|]|\\
 |\begin{problem}[|\textit{opts}|]|
+\end{tabular}
 \end{center}
 %
 The argument \textit{opt}
@@ -523,22 +612,26 @@
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \DescribeMacro{\defsheetdata}
+\DescribeMacro{\setsheetdata}
 \DescribeMacro{\getsheetdata}
 \DescribeMacro{\sheetdataempty}
 \DescribeMacro{\defproblemdata}
+\DescribeMacro{\setproblemdata}
 \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|:
+The following directives are analogous to |\defexercisedata|,
+|\exercisedata|, |\getexercisedata| and |\exercisedataempty|:
 %
 \begin{center}
 \begin{tabular}{l}
 |\defsheetdata{|\textit{key}|}|\\
+|\setsheetdata{|\textit{data}|}|\\
 |\getsheetdata{|\textit{key}|}|\\
 |\sheetdataempty{|\textit{key}|}|%
   |{|\textit{empty code}|}{|\textit{filled code}|}|\\[1ex]
 |\defproblemdata{|\textit{key}|}|\\
+|\setproblemdata{|\textit{data}|}|\\
 |\getproblemdata{|\textit{key}|}|\\
 |\problemdataempty{|\textit{key}|}|%
   |{|\textit{empty code}|}{|\textit{filled code}|}|
@@ -631,12 +724,15 @@
 \item |comment|:
 some comment on the problem.
 \item |optional|
-(enabled by default):
+(display 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}
 %
+By default, only the |optional| items are displayed,
+all other types of items are hidden;
+controlling the display for each type of item is described below.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \DescribeMacro{extdata}
@@ -740,16 +836,19 @@
 [\textit{regular}][|+|\textit{bonus}] where 0 components are omitted.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\DescribeMacro{pointsat}
-\DescribeMacro{subpointsat}
+\DescribeMacro{problempointsat}
+\DescribeMacro{subproblempointsat}
+\DescribeMacro{solutionpointsat}
 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|%
+|\exercisestyle{problempointsat=start|\textbar|start*|\textbar|margin|%
   \textbar|end|\textbar|manual|\textbar|off}|\\
-|\problemstyle{subpoints=start|\textbar|start*|\textbar|margin|%
+|\exercisestyle{subproblempointsat=start|\textbar|start*|\textbar|margin|%
+  \textbar|end|\textbar|manual|\textbar|off}|\\
+|\exercisestyle{solutionpointsat=start|\textbar|start*|\textbar|margin|%
   \textbar|end|\textbar|manual|\textbar|off}|
 \end{tabular}
 \end{center}
@@ -785,7 +884,10 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \DescribeMacro{\getsheetpoints}
 \DescribeMacro{\getproblempoints}
+\DescribeMacro{\getsubproblempoints}
+\DescribeMacro{\getsolutionpoints}
 \DescribeMacro{\extractpoints}
+\DescribeMacro{\switchpoints}
 The package allows to read the point totals
 for other sheets and problems:
 %
@@ -792,17 +894,36 @@
 \begin{center}
 \begin{tabular}{l}
 |\getsheetpoints{|\textit{tag}|}|\\
-|\getproblempoints{|\textit{tag}|}|
+|\getproblempoints{|\textit{tag}|}|\\
+|\getsubproblempoints{}|\\
+|\getsolutionpoints{}|
 \end{tabular}
 \end{center}
 %
 Here \textit{tag} is the tag assigned to the corresponding sheet or problem,
 see \secref{sec:labels}.
+An empty argument \textit{tag} refers to the current
+sheet, (sub)problem or solution.
 If bonus points are used, the points will be returned
 in the format [\textit{regular}][|+|\textit{bonus}];
 the components \textit{regular} and \textit{bonus}
 can be extracted from the returned expression
 by |\extractpoints| and |\extractpoints*|, respectively.
+A convenient case switch of the returned value can be performed by:
+%
+\begin{center}
+|\switchpoints{|\textit{reg}|}{|\textit{bonus}|}{|\textit{both}|}{|%
+\textit{none}|}{|\textit{val}|}|
+\end{center}
+%
+Here \textit{val} is the value returned from the points register,
+\textit{reg} is displayed for purely regular points,
+\textit{bonus} is displayed for purely bonus points,
+\textit{both} is displayed for mixed points,
+\textit{none} is displayed for no points.
+In each of the four expressions,
+|#1| will be replaced by the regular points
+and |#2| by the bonus points.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \DescribeMacro{\awardpoints}
@@ -1103,24 +1224,30 @@
 %
 \begin{itemize}
 \item |solutionbelow=|\textit{pos}
-(can take values |here|, |here*|, |subproblem|, |subproblem*|,
+(can take values |here|, |subproblem|, |subproblem*|,
 |problem|, |problem*|, |sheet| and |manual|;
 initially set to |subproblem|) --
-positions the solutions below the indicated blocks;
+positions the solutions below the indicated environments;
 see \secref{sec:solutions} for details.
 
-\item |pointsat=|\textit{pos}
+\item |problempointsat=|\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}
+\item |subproblempointsat=|\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 |solutionpointsat=|\textit{pos}
+(can take values |start|, |start*|, |margin|, |end| and |manual|;
+initially set to |end|) --
+displays points in solutions 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
@@ -1340,6 +1467,21 @@
 (|prob:\problemtag|; can be adjusted)
 to problems according to their tag |\problemtag|.
 
+\item |solutionbuf|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |true|) --
+enable/disable buffering for |solution| environments
+in order to control their display;
+disabling buffering can be helpful
+in debugging faulty |solution| environments;
+it might also resolve some tokenisation issues in special circumstances;
+note that the display of solutions cannot be suppressed
+with |\exercisesetup{solutions=false}| when buffering if disabled.
+
+\item |problembuf|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable buffering for |problem| environments
+in order to control their display.
+
 \end{itemize}
 %
 
@@ -1533,12 +1675,16 @@
 %
 \begin{itemize}
 \item
+Add a section on useful combinations of customisation settings
+to achieve specific goals. Please send suggestions.
+\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.
+(for a version containing only solutions):
+this is difficult to implement because the problem environment
+cannot simply be discarded, but would have to be scanned very carefully
+for the embedded solution;
+instead process problems to some document and save solutions to file,
+then read solutions from different document.
 \item
 Define structures for multiple-choice questions.
 \end{itemize}
@@ -1547,6 +1693,37 @@
 \subsection{Revision History}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.3:} 2019/06/15
+
+\begin{itemize}
+\item
+control display of |problem| environments via
+package option |problembuf|:
+manual display, write to file, disable individual problems
+\item
+|solutionbelow| mode |here*| superseded by
+package option |solutionbuf|
+\item
+display total points within solution: |solutionpointsat|
+(thanks to Till Bargheer for suggestion)
+\item
+read points for current sheet, (sub)problem and solution
+(thanks to Johannes Hahn for suggestion)
+\item
+case switch for bonus points
+(thanks to Johannes Hahn for suggestion)
+\item
+option to |disable| particular problems,
+control by hook function
+(thanks to Manuel Benz for suggestion)
+\item
+provided interface |\showfracpoints| and |\exerciseconfig{frac}|
+for fractional points display
+\item
+filename extensions configurable
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \paragraph{v3.2:} 2019/05/01
 
 \begin{itemize}
@@ -1555,7 +1732,7 @@
 |points=|[\textit{regular}][|+|\textit{bonus}]
 \item
 |solutionbelow| mode |here*| added
-for direct processing of the solution block
+for direct processing of the solution environment
 \item
 multipart sample added
 \end{itemize}
@@ -1569,10 +1746,11 @@
 package \href{http://ctan.org/pkg/calc}{\textsf{calc}}
 (thanks to Johannes Hahn for bug report)
 \item
-fix style |fracpoints| in combination with some [|sub|]|pointsat| choices
+fix style |fracpoints| in combination
+with some [|sub|]|problempointsat| choices
 (thanks to Johannes Hahn for bug report)
 \item
-fix spacing for [|sub|]|pointsat=margin|
+fix spacing for [|sub|]|problempointsat=margin|
 (thanks to Johannes Hahn for bug report)
 \end{itemize}
 
@@ -1750,6 +1928,16 @@
 \exerciseconfig{countersubproblemmax}{vii)}
 %    \end{macrocode}
 
+% Automatically display an asterisk for all
+% subproblems with bonus points only;
+% remove space to separate items:
+%    \begin{macrocode}
+\exerciseconfig{insertsubprobleminfo}{%
+ \switchpoints{}{\addprobleminfo*{%
+   \hspace{-\getexerciseconfig{skipsubprobleminfo}}*}}%
+  {}{}{\getsubproblempoints{}}}
+%    \end{macrocode}
+
 % Redefine the terms to be used for sheet(s);
 % here, a German version:
 %    \begin{macrocode}
@@ -1761,7 +1949,7 @@
 % change margin display to use the left margin;
 % use the abbreviated form `$n$p.':
 %    \begin{macrocode}
-\exercisestyle{pointsat=margin}
+\exercisestyle{problempointsat=margin}
 \reversemarginpar
 \exerciseconfig{composepointsmargin}[1]{#1p.}
 \exerciseconfig{composepointspairmargin}[2]{
@@ -1854,7 +2042,7 @@
 \end{equation}
 %    \end{macrocode}
 
-% Provide a solution for the subproblem (within the subproblem block):
+% Provide a solution for the subproblem (within the subproblem environment):
 %    \begin{macrocode}
 \begin{solution}
 The result is
@@ -2220,7 +2408,7 @@
 % Number figures within sheet to provide a stable numbering
 % upon insertion/deletion of new figures or partial compilation.
 % Do not warn about unused figures when preparing without solutions
-% (figures for solutions should be declared outside |solution| blocks):
+% (figures for solutions should be declared outside |solution| environments):
 %    \begin{macrocode}
 \mpostsetup{checksum}
 \if\draftver y\mpostsetup{now,nowall}\fi
@@ -2620,7 +2808,7 @@
 
 % Problem body without a figure;
 % this time the |solution| environments are
-% included in the |subproblem| blocks:
+% included in the |subproblem| environments:
 %    \begin{macrocode}
 \lorem
 
@@ -2674,7 +2862,7 @@
 % allows to compile each problem individually.
 %
 % To that end, prepare a file |exfserp|\textit{nn}|.tex|
-% containing the problem block |\begin{problem}| \ldots |\end{problem}|.
+% containing the |problem| environment.
 % This file should start with:
 %    \begin{macrocode}
 %%\providecommand{\printsol}{n}
@@ -2995,7 +3183,7 @@
 % The package loads the package
 % \textsf{verbatim} and \textsf{xkeyval}
 % if not yet present.
-% \textsf{verbatim} is used for solution block reading
+% \textsf{verbatim} is used for solution environment reading
 % and \textsf{xkeyval} is used for extended options processing:
 %    \begin{macrocode}
 \RequirePackage{verbatim}
@@ -3061,7 +3249,6 @@
   {\def\exf at tmp{#2}\ifx#1\exf at tmp#3\fi}
 %    \end{macrocode}
 
-
 % \macro{\exf at href}
 % Display text with hyperreference passed by macro |#1|
 % (in case \textsf{hyperref} is loaded
@@ -3167,6 +3354,15 @@
 %    \begin{macrocode}
 \define at boolkey{exf at setup}[exf@]{warntext}[true]{}
 %    \end{macrocode}
+% Activate buffering of solutions:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[exf@]{solutionbuf}[true]{}
+\exf at solutionbuftrue
+%    \end{macrocode}
+% Activate buffering of problems:
+%    \begin{macrocode}
+\define at boolkey{exf at setup}[exf@]{problembuf}[true]{}
+%    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Processing.}
@@ -3298,6 +3494,10 @@
 %    \begin{macrocode}
 \exerciseconfig{styletitlesolutions}{\normalsize}
 %    \end{macrocode}
+% Style for problem block title:
+%    \begin{macrocode}
+\exerciseconfig{styletitleproblems}{\Large}
+%    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Spacing.}
@@ -3364,21 +3564,38 @@
 \exerciseconfig{skipsolutionitemsub}{0pt}
 %    \end{macrocode}
 
-% Spaces related to blocks of solutions;
+% Spaces related to solution blocks;
 % 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:
+% Space above problem titles in a solution block:
 %    \begin{macrocode}
-\exerciseconfig{skipsolutionsproblem}{1.0ex plus 0ex minus 0.5ex}
+\exerciseconfig{skipsolutionsproblemabove}{1.0ex plus 0ex minus 0.5ex}
 %    \end{macrocode}
+% Space following problem titles in a solution block
+% (with legacy definition):
+%    \begin{macrocode}
+\exerciseconfig{skipsolutionsproblemtitle}{1.0ex plus 0ex minus 0.5ex}
+\exerciseconfig{skipsolutionsproblem}{\exf at config@skipsolutionsproblemtitle}
+%    \end{macrocode}
 % Space following title of a solution block:
 %    \begin{macrocode}
 \exerciseconfig{skipsolutionstitle}{1.0ex plus 0ex minus 0.5ex}
 %    \end{macrocode}
 
+% Spaces related to problem blocks;
+% space above and below a problem block:
+%    \begin{macrocode}
+\exerciseconfig{skipproblemsabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipproblemsbelow}{1.5ex plus 0.5ex minus 1ex}
+%    \end{macrocode}
+% Space following title of a problem block:
+%    \begin{macrocode}
+\exerciseconfig{skipproblemstitle}{1.0ex plus 0ex minus 0.5ex}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Hook Code.}
 %
@@ -3410,6 +3627,14 @@
 %    \begin{macrocode}
 \exerciseconfig{insertsolutionsafter}{}
 %    \end{macrocode}
+% Code to insert before a problem block is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertproblemsbefore}{}
+%    \end{macrocode}
+% Code to insert after a problem block is displayed:
+%    \begin{macrocode}
+\exerciseconfig{insertproblemsafter}{}
+%    \end{macrocode}
 % Code to insert before a problem is displayed:
 %    \begin{macrocode}
 \exerciseconfig{insertproblembefore}{}
@@ -3428,6 +3653,10 @@
 %    \begin{macrocode}
 \exerciseconfig{insertprobleminfo}{}
 %    \end{macrocode}
+% Code to determine the display of problems:
+%    \begin{macrocode}
+\exerciseconfig{insertproblemselect}[1]{}
+%    \end{macrocode}
 % Analogous definitions for subproblems:
 %    \begin{macrocode}
 \exerciseconfig{insertsubproblembefore}{}
@@ -3546,11 +3775,21 @@
 \exerciseconfig{composetitlesolutions}%
   {\getexerciseconfig{termsolutions}}
 %    \end{macrocode}
+% Compose title for problem block:
+%    \begin{macrocode}
+\exerciseconfig{composetitleproblems}%
+  {\getexerciseconfig{termproblems}}
+%    \end{macrocode}
 % Compose table of contents line for solution block:
 %    \begin{macrocode}
 \exerciseconfig{composetocsolutions}%
   {\getexerciseconfig{composetitlesolutions}}
 %    \end{macrocode}
+% Compose table of contents line for problem block:
+%    \begin{macrocode}
+\exerciseconfig{composetocproblems}%
+  {\getexerciseconfig{composetitleproblems}}
+%    \end{macrocode}
 % Compose sectional title for solution following a single problem;
 % arguments are problem number and raw title:
 %    \begin{macrocode}
@@ -3557,7 +3796,7 @@
 \exerciseconfig{composetitlesolutionsproblemsingle}[2]%
   {\getexerciseconfig{termsolution}}
 %    \end{macrocode}
-% Compose sectional title for solution of one problem within a block;
+% Compose sectional title for solution of one problem within a solution block;
 % arguments are problem number and raw title:
 %    \begin{macrocode}
 \exerciseconfig{composetitlesolutionsproblemmulti}[2]%
@@ -3647,6 +3886,21 @@
   (\getexerciseconfig{composepointspair}{#1}{#2}*%
    \exerciseifnotempty{#3}{; #3})\fi}
 %    \end{macrocode}
+% Compose pairs of points for designated situations:
+%    \begin{macrocode}
+\exerciseconfig{composepointspairbodyproblem}[2]{%
+  \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairbodysubproblem}[2]{%
+  \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairbodysolution}[2]{%
+  \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairstartproblem}[2]{%
+  \getexerciseconfig{composepointspairstart}{#1}{#2}}
+\exerciseconfig{composepointspairstartsubproblem}[2]{%
+  \getexerciseconfig{composepointspairstart}{#1}{#2}}
+\exerciseconfig{composepointspairstartsolution}[2]{%
+  \getexerciseconfig{composepointspairstart}{#1}{#2}}
+%    \end{macrocode}
 
 % Display points in the margin:
 %    \begin{macrocode}
@@ -3682,7 +3936,8 @@
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Further Definitions.}
 %
-% \macro{label...}
+% \macro{labelsheet}
+% \macro{labelproblem}
 % Templates for automatic generation of labels from tags:
 %    \begin{macrocode}
 \exerciseconfig{labelsheet}[1]{sheet:#1}
@@ -3696,10 +3951,19 @@
 %    \begin{macrocode}
 \exerciseconfig{toclevelsheet}{}
 \exerciseconfig{toclevelproblem}{}
+\exerciseconfig{toclevelproblems}{}
 \exerciseconfig{toclevelsolution}{}
 \exerciseconfig{toclevelsolutions}{}
 %    \end{macrocode}
 
+% \macro{extsolutions}
+% \macro{extproblems}
+% Filename extension for solution and problem blocks:
+%    \begin{macrocode}
+\exerciseconfig{extsolutions}{.sol}
+\exerciseconfig{extproblems}{.prb}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \subsection{Styles}
 % \label{sec:imp-styles}
@@ -3741,13 +4005,20 @@
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Default Exercise Styles.}
 %
+% \macro{problemmanual}
+% Delay display of problems:
+%    \begin{macrocode}
+\define at boolkey{exf at style}[exf@]{problemmanual}[true]{}
+\exf at problemmanualfalse
+%    \end{macrocode}
+%
 % \macro{solutionbelow}
 % Choose location for solutions:
 %    \begin{macrocode}
 \def\exf at solutionbelow{subproblem}
 \define at choicekey{exf at style}{solutionbelow}%
-  {here,here*,subproblem,subproblem*,problem,problem*,sheet,manual}%
-  {\ifexf at infile\else\def\exf at solutionbelow{#1}\fi}
+  {here,subproblem,subproblem*,problem,problem*,sheet,manual}%
+  {\ifexf at solfile@open\else\gdef\exf at solutionbelow{#1}\fi}
 %    \end{macrocode}
 %
 % \macro{sheetequation}
@@ -3761,16 +4032,26 @@
 \exf at style@solutionequationtrue
 %    \end{macrocode}
 %
-% \macro{pointsat}
-% \macro{subpointsat}
-% Choose where points of problems and subproblems are displayed:
+% \macro{problempointsat}
+% \macro{subproblempointsat}
+% \macro{solutionpointsat}
+% Choose where points of (sub)problems and solutions are displayed:
 %    \begin{macrocode}
 \def\exf at pointsat{start}
+\define at choicekey{exf at style}{problempointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at pointsat{#1}}
 \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}{subproblempointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at subpointsat{#1}}
 \define at choicekey{exf at style}{subpointsat}%
   {start,start*,margin,end,manual,off}{\def\exf at subpointsat{#1}}
+\def\exf at solpointsat{off}
+\define at choicekey{exf at style}{solutionpointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at solpointsat{#1}}
+\define at choicekey{exf at style}{solpointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at solpointsat{#1}}
 %    \end{macrocode}
 %
 % \macro{problemby}
@@ -3800,7 +4081,7 @@
 % Use vulgar fractions to display binary fractional points:
 %    \begin{macrocode}
 \defexercisestyle{fracpoints}%
-  {\exerciseconfig{composepointsnum}[1]{\protect\exf at nicefrac{##1}}}
+  {\exerciseconfig{composepointsnum}[1]{\protect\showfracpoints{##1}}}
 %    \end{macrocode}
 %
 % \macro{twoside}
@@ -3843,7 +4124,8 @@
 %    \begin{macrocode}
 \defexercisestyle{solutionsep}{%
   \exerciseconfig{insertsolutionsbefore}{\hrule\nopagebreak[3]\vspace{0.5ex}}%
-  \exerciseconfig{insertsolutionsafter}{\nopagebreak[3]\vspace{1.0ex}\hrule}}
+  \exerciseconfig{insertsolutionsafter}%
+   {\removelastskip\nopagebreak[3]\vspace{1.0ex}\hrule}}
 %    \end{macrocode}
 % \macro{plainheader}
 % Declare a simple sheet header with some configurable options;
@@ -3967,8 +4249,13 @@
   \define at key{exf at sheet}{#1}%
    {\exf at csdo\def{exf at data@sheet@#1}{##1}}}
 %    \end{macrocode}
+% \macro{\setsheetdata}
+% Set sheet metadata:
+%    \begin{macrocode}
+\newcommand{\setsheetdata}[1]{\setkeys{exf at sheet}{#1}}
+%    \end{macrocode}
 % \macro{\getsheetdata}
-% Read global metadata:
+% Read sheet metadata:
 %    \begin{macrocode}
 \newcommand{\getsheetdata}[1]{\csname exf at data@sheet@#1\endcsname}
 %    \end{macrocode}
@@ -4005,7 +4292,7 @@
 % \paragraph{Problem Metadata.}
 %
 % \macro{\defproblemdata}
-% Declare sheet metadata field
+% Declare problem 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}
@@ -4014,8 +4301,13 @@
   \define at key{exf at problem}{#1}%
    {\exf at csdo\def{exf at data@problem@#1}{##1}}}
 %    \end{macrocode}
+% \macro{\setproblemdata}
+% Set problem metadata:
+%    \begin{macrocode}
+\newcommand{\setproblemdata}[1]{\setkeys{exf at problem,exf at scanproblem}{#1}}
+%    \end{macrocode}
 % \macro{\getproblemdata}
-% Read global metadata:
+% Read problem metadata:
 %    \begin{macrocode}
 \newcommand{\getproblemdata}[1]{\csname exf at data@problem@#1\endcsname}
 %    \end{macrocode}
@@ -4035,10 +4327,10 @@
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \paragraph{Problem Block Code.}
+% \paragraph{Problem Environment Code.}
 %
 % \macro{\exf at addmargin}
-% Define a length for block margin:
+% Define a length for environment margin:
 %    \begin{macrocode}
 \newlength\exf at addmargin
 %    \end{macrocode}
@@ -4080,7 +4372,7 @@
   {\exf at prepend@def\exf at intro{#1\hspace{\exf at intro@skip}}}
 %    \end{macrocode}
 % \macro{\exf at open@block}
-% Open block, set margin, compose opening line:
+% Open environment, set margin, compose opening line:
 %    \begin{macrocode}
 \newcommand{\exf at open@block}[1]{%
   \advance\leftskip\exf at addmargin%
@@ -4093,7 +4385,7 @@
   \fi}%
 %    \end{macrocode}
 % \macro{\exf at close@block}
-% Close block, undo margin:
+% Close environment, undo margin:
 %    \begin{macrocode}
 \newcommand{\exf at close@block}{%
   \advance\leftskip-\exf at addmargin%
@@ -4287,21 +4579,23 @@
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{File Output.}
 %
-% \macro{\ifexf at infile}
-% Conditional whether an output file is presently in use:
+% \macro{\ifexf at solfile@open}
+% Conditional whether output files are presently in use:
 %    \begin{macrocode}
-\newif\ifexf at infile\exf at infilefalse
+\newif\ifexf at solfile@open\exf at solfile@openfalse
+\newif\ifexf at probfile@open\exf at probfile@openfalse
 %    \end{macrocode}
-% \macro{\exf at out}
-% Reserve file handle:
+% \macro{\exf at solfile}
+% Reserve file handles:
 %    \begin{macrocode}
-\newwrite\exf at out
+\newwrite\exf at solfile
+\newwrite\exf at probfile
 %    \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}}
+\newcommand{\exf at writeline}[2]{\immediate\write#1{#2}}
 %    \end{macrocode}
 
 % \macro{\exf at linesep}
@@ -4320,82 +4614,120 @@
   l.\the\inputlineno}
 %    \end{macrocode}
 
-% \macro{\exf at startfile}
-% Open a new file |#1.sol| (do nothing if already open);
+% \macro{\exf at start@solfile}
+% Open a new solution 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}%
+\newcommand{\exf at start@solfile}[1]{%
+  \ifexf at solfile@open\else%
+   \exercisestyle{solutionbelow=manual}%
+   \global\exf at solfile@opentrue%
    \edef\exf at tmp{#1}%
-   \immediate\openout\exf at out\exf at tmp.sol%
-   \exf at writeline{\@percentchar%
+   \immediate\openout\exf at solfile\exf at tmp\exf at config@extsolutions\relax%
+   \exf at writeline\exf at solfile{\@percentchar%
     generated from file `\jobname' by exframe.sty}%
-   \ifexf at lineno\exf at writeline{\exf at lineno}\fi%
-   \exf at writeline{}%
+   \ifexf at lineno\exf at writeline\exf at solfile{\exf at lineno}\fi%
+   \exf at writeline\exf at solfile{}%
   \fi}
 %    \end{macrocode}
 
-% \macro{\exf at closefile}
-% Close file (if open);
+% \macro{\exf at close@solfile}
+% Close solution 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%
+\newcommand{\exf at close@solfile}{%
+  \ifexf at solfile@open%
+   \ifexf at lineno\exf at writeline\exf at solfile{\exf at linesep}%
+    \exf at writeline\exf at solfile{\exf at lineno}\fi%
+   \exf at writeline\exf at solfile{\@backslashchar endinput}%
+   \immediate\closeout\exf at solfile%
+   \global\exf at solfile@openfalse%
   \fi}
 %    \end{macrocode}
 
-% Make sure to properly close file at the end:
+% \macro{\exf at start@probfile}
+% Open a new problem file |#1.prb| (do nothing if already open);
+% indicate source, switch to manual problem display mode:
 %    \begin{macrocode}
-\AtEndDocument{\exf at closefile}
+\newcommand{\exf at start@probfile}[1]{%
+  \ifexf at probfile@open\else%
+   \global\exf at probfile@opentrue%
+   \edef\exf at tmp{#1}%
+   \immediate\openout\exf at probfile\exf at tmp\exf at config@extproblems\relax%
+   \exf at writeline\exf at probfile{\@percentchar%
+    generated from file `\jobname' by exframe.sty}%
+   \ifexf at lineno\exf at writeline\exf at probfile{\exf at lineno}\fi%
+   \exf at writeline\exf at probfile{}%
+  \fi}
 %    \end{macrocode}
 
+% \macro{\exf at close@probfile}
+% Close problem file (if open);
+% indicate position, close and reset variables:
+%    \begin{macrocode}
+\newcommand{\exf at close@probfile}{%
+  \ifexf at probfile@open%
+   \ifexf at lineno\exf at writeline\exf at probfile{\exf at linesep}%
+    \exf at writeline\exf at probfile{\exf at lineno}\fi%
+   \exf at writeline\exf at probfile{\@backslashchar endinput}%
+   \immediate\closeout\exf at probfile%
+   \global\exf at probfile@openfalse%
+  \fi}
+%    \end{macrocode}
+
+% Make sure to properly close files at the end:
+%    \begin{macrocode}
+\AtEndDocument{\exf at close@solfile\exf at close@probfile}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \paragraph{Solution Buffer.}
+% \paragraph{Buffers.}
 %
-% \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:
+% \macro{\exf at solbuf}
+% \macro{\exf at probbuf}
+% \macro{\ifexf at solbuf@clean}
+% \macro{\ifexf at probbuf@clean}
+% Declare token buffers for storing problems and solutions
+% and conditionals indicating whether the buffers have been used:
 %    \begin{macrocode}
-\newtoks\exf at buf
-\newif\ifexf at bufclean\exf at bufcleantrue
+\newtoks\exf at solbuf
+\newtoks\exf at probbuf
+\newif\ifexf at solbuf@clean\exf at solbuf@cleantrue
+\newif\ifexf at probbuf@clean\exf at probbuf@cleantrue
 %    \end{macrocode}
-
-% \macro{\exf at clearbuf}
-% Clear solution buffer and mark clean:
+% \macro{\exf at clear@solbuf}
+% \macro{\exf at clear@probbuf}
+% Clear a buffer and mark clean:
 %    \begin{macrocode}
-\def\exf at clearbuf{\global\exf at bufcleantrue\global\exf at buf={}}
+\def\exf at clear@solbuf{\global\exf at solbuf@cleantrue\global\exf at solbuf={}}
+\def\exf at clear@probbuf{\global\exf at probbuf@cleantrue\global\exf at probbuf={}}
 %    \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}}
+\def\exf at append@buf#1#2{\global#1=\expandafter{\the#1#2}}
 %    \end{macrocode}
-% \macro{\exf at addbufline}
+% \macro{\exf at addline}
 % 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}}}
+\def\exf at addline#1#2{{\protected at edef\exf at tmp{#2}%
+  \exf at exparg{\exf at append@buf#1}{\exf at tmp^^J}}}
 %    \end{macrocode}
-
-% \macro{\exf at sourcebuf}
-% Source the solution buffer into the document:
+% \macro{\exf at source@buf}
+% Source a buffer into the document:
 %    \begin{macrocode}
-\def\exf at sourcebuf{\exf at exptwo\scantokens{\the\exf at buf}}
+\def\exf at source@buf#1{\exf at exptwo\scantokens{\the#1}}
 %    \end{macrocode}
-% \macro{\exf at writebuf}
+% \macro{\exf at write@buf}
 % Write the buffer into the solution file:
 %    \begin{macrocode}
-\def\exf at writebuf{\exf at writeline{\the\exf at buf}}
+\def\exf at write@buf#1#2{\exf at writeline#1{\the#2}}
 %    \end{macrocode}
 
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Verbatim Processing.}
+%
 % \macro{\exf at verbatim}
 % Start reading the buffer from the environment body:
 %    \begin{macrocode}
@@ -4404,7 +4736,8 @@
   \@bsphack%
   \let\do\@makeother\dospecials%
   \catcode`\^^M\active%
-  \def\verbatim at processline{\exf at exptwo\exf at append@buf{\the\verbatim at line^^J}}%
+  \def\verbatim at processline{\exf at exptwo\exf at verbatim@process%
+   {\the\verbatim at line^^J}}%
   \verbatim at start}
 %    \end{macrocode}
 
@@ -4415,8 +4748,8 @@
 %    \end{macrocode}
 
 % \macro{\exf at scanblock}
-% Scan an optional argument from a verbatim block;
-% allow for an empty block and an empty first line;
+% Scan an optional argument from a verbatim environment;
+% allow for an empty environment and an empty first line;
 % argument |#1| is macro to be called eventually:
 %    \begin{macrocode}
 \def\exf at scanblock#1{%
@@ -4429,12 +4762,12 @@
 %    \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|):
+% Check for optional argument (|[|) and for environment 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?!):
+% Handle empty environment, hopefully environment matches (otherwise?!):
 %    \begin{macrocode}
 \def\exf at scanblock@end#1\end#2{%
   \def\exf at tmp{#2}\ifx\exf at tmp\@currenvir%
@@ -4520,6 +4853,20 @@
   \expandafter#1\exf at tmp}
 %    \end{macrocode}
 
+% \macro{\switchpoints}
+% Extract main (plain) and bonus (starred) part from points,
+% and execute one of three:
+%    \begin{macrocode}
+\newcommand{\switchpoints}[5]{\edef\exf at tmp{#5}%
+  \exf at exptwo\exf at scanpoints\exf at tmp\exf at tmp++&%
+  \expandafter\exf at switchpoints\exf at tmp{#1}{#2}{#3}{#4}}
+\newcommand{\exf at switchpoints}[6]{%
+  \ifdim#2pt=0pt\ifdim#1pt=0pt\def\exf at tmp##1##2{#6}%
+   \else\def\exf at tmp##1##2{#3}\fi%
+  \else\ifdim#1pt=0pt\def\exf at tmp##1##2{#4}%
+   \else\def\exf at tmp##1##2{#5}\fi\fi\exf at tmp{#1}{#2}}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Tools.}
 %
@@ -4571,12 +4918,12 @@
 \def\exf at splitdecimal#1.#2.#3&{\def\exf at splitint{#1}\def\exf at splitdec{#2}}
 %    \end{macrocode}
 
-% \macro{\exf at nicefrac}
+% \macro{\showfracpoints}
 % 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]{%
+\newcommand{\showfracpoints}[1]{%
   \edef\exf at tmp{#1}%
   \expandafter\exf at splitsign\exf at tmp--&%
   \expandafter\exf at splitdecimal\exf at splitnum..&%
@@ -4584,22 +4931,22 @@
   \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%
+  \ifnum\exf at splitdec=5\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{2}}\fi%
+  \ifnum\exf at splitdec=25\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{4}}\fi%
+  \ifnum\exf at splitdec=75\def\exf at tmp{\exf at config@frac{\exf at splitint}{3}{4}}\fi%
+  \ifnum\exf at splitdec=125\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{8}}\fi%
+  \ifnum\exf at splitdec=375\def\exf at tmp{\exf at config@frac{\exf at splitint}{3}{8}}\fi%
+  \ifnum\exf at splitdec=625\def\exf at tmp{\exf at config@frac{\exf at splitint}{5}{8}}\fi%
+  \ifnum\exf at splitdec=875\def\exf at tmp{\exf at config@frac{\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}
+% \macro{\exf at config@frac}
 % Display a vulgar fraction
 % such as 12$^3\mskip-4mu/\mskip-2mu_4$:
 %    \begin{macrocode}
-\newcommand{\exf at intfrac}[3]{%
+\newcommand{\exf at config@frac}[3]{%
   \ifnum#1=0\else#1\fi%
   \ifnum#2=0\else$%
    ^{\exf at text{#2}}%
@@ -4629,10 +4976,13 @@
    {\exf at formatpoints{#1}{#2}}}}
 %    \end{macrocode}
 % \macro{\getsheetpoints}
-% Read sheet points stored in |.aux| file:
+% Read points for current sheet or from |.aux| file:
 %    \begin{macrocode}
-\newcommand{\getsheetpoints}[1]{\ifcsname exf at sheetpoints@#1\endcsname%
-  \csname exf at sheetpoints@#1\endcsname\else 0\fi}
+\newcommand{\getsheetpoints}[1]{\if&#1&%
+   \ifdefined\exf at sheet@points%
+    \expandafter\exf at formatpoints\exf at sheet@points\else 0\fi%
+  \else\ifcsname exf at sheetpoints@#1\endcsname%
+   \csname exf at sheetpoints@#1\endcsname\else 0\fi\fi}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -4657,21 +5007,34 @@
    {\exf at formatpoints{#1}{#2}}}}
 %    \end{macrocode}
 % \macro{\getproblempoints}
-% Read problem points stored in |.aux| file:
+% Read points for current problem or from |.aux| file:
 %    \begin{macrocode}
-\newcommand{\getproblempoints}[1]{\ifcsname exf at problempoints@#1\endcsname%
-  \csname exf at problempoints@#1\endcsname\else 0\fi}
+\newcommand{\getproblempoints}[1]{\if&#1&%
+   \ifdefined\exf at problem@points%
+    \expandafter\exf at formatpoints\exf at problem@points\else 0\fi%
+  \else\ifcsname exf at problempoints@#1\endcsname%
+   \csname exf at problempoints@#1\endcsname\else 0\fi\fi}
 %    \end{macrocode}
+% \macro{\getsubproblempoints}
+% Read points for current subproblem:
+%    \begin{macrocode}
+\newcommand{\getsubproblempoints}[1]{\if&#1&%
+   \ifdefined\exf at subproblem@points%
+    \expandafter\exf at formatpoints\exf at subproblem@points\else 0\fi%
+  \else 0\fi}
+%    \end{macrocode}
 
 % \macro{\showpoints}
 % Show points within a problem or subproblem:
 %    \begin{macrocode}
 \newcommand{\showpoints}{%
-  \ifdefined\exf at in@subproblem\exf at outpoints{\exf at ensuretext}%
-   {\exf at config@composepointspairbody}{\exf at subproblem@points}%
+  \ifdefined\exf at in@solution\exf at outpoints{\exf at ensuretext}%
+   {\exf at config@composepointspairbodysolution}{\exf at solution@points at show}%
+  \else\ifdefined\exf at in@subproblem\exf at outpoints{\exf at ensuretext}%
+   {\exf at config@composepointspairbodysubproblem}{\exf at subproblem@points at show}%
   \else\ifdefined\exf at in@problem\exf at outpoints{\exf at ensuretext}%
-   {\exf at config@composepointspairbody}{\exf at problem@points at show}%
-  \fi\fi}
+   {\exf at config@composepointspairbodyproblem}{\exf at problem@points at show}%
+  \fi\fi\fi}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -4701,17 +5064,23 @@
 \newcommand{\awardpoints}{\@ifstar\exf at awardpointsalt\exf at awardpointsreg}
 %    \end{macrocode}
 
+% \macro{\getsolutionpoints}
+% Read points for current solution:
+%    \begin{macrocode}
+\newcommand{\getsolutionpoints}[1]{\if&#1&%
+   \ifdefined\exf at solution@points%
+    \expandafter\exf at formatpoints\exf at solution@points\else 0\fi%
+  \else 0\fi}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \subsection{Environments}
-% \label{sec:imp-env}
+% \subsection{Sheet Environment}
+% \label{sec:imp-sheet}
 %
-% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \paragraph{Sheets.}
-%
 % \macro{exf at sheet}
 % Define options for |sheet| environment:
 %    \begin{macrocode}
-\define at key{exf at sheet}{points}{\exf at scanpoints\exf at points@given#1++&}
+\define at key{exf at sheet}{points}{\exf at scanpoints\exf at sheet@points#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}}
@@ -4738,7 +5107,7 @@
 %    \end{macrocode}
 % Reset optional arguments, process arguments:
 %    \begin{macrocode}
-  \let\exf at points@given\@undefined%
+  \let\exf at sheet@points\@undefined%
   \def\sheettag{\csname the\exf at sheetcounter\endcsname}%
   \let\exf at sheet@points at total\@undefined%
   \let\exf at label\@undefined%
@@ -4751,12 +5120,13 @@
 %    \end{macrocode}
 % Set points from explicit input or from |.aux| storage:
 %    \begin{macrocode}
-  \let\exf at sheet@points\@undefined%
-  \ifdefined\exf at points@given%
-   \let\exf at sheet@points\exf at points@given%
-  \else\ifcsname exf at sheetpoints@\sheettag\endcsname%
-   \exf at csdotwo\let\exf at tmp{exf at sheetpoints@\sheettag}%
-   \exf at exptwo\exf at scanpoints\exf at sheet@points\exf at tmp++&%
+  \ifdefined\exf at sheet@points%
+   \let\exf at sheet@points at given\exf at empty%
+  \else%
+   \let\exf at sheet@points at given\@undefined%
+   \ifcsname exf at sheetpoints@\sheettag\endcsname%
+    \exf at csdotwo\let\exf at tmp{exf at sheetpoints@\sheettag}%
+    \exf at exptwo\exf at scanpoints\exf at sheet@points\exf at tmp++&%
   \fi\fi%
 %    \end{macrocode}
 % Process metadata:
@@ -4782,7 +5152,7 @@
 % End of environment;
 % perform sanity check on total points if given explicitly:
 %    \begin{macrocode}
- {\ifdefined\exf at points@given%
+ {\ifdefined\exf at sheet@points at given%
    \exf at warnmismatch{\exf at sheetname}{\exf at sheetcounter}%
     {\exf at sheet@points at total}{\exf at sheet@points}%
 %    \end{macrocode}
@@ -4832,22 +5202,26 @@
   \thispagestyle{empty}\hbox{}\newpage\fi\fi}
 %    \end{macrocode}
 
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Problem Environment}
+% \label{sec:imp-problem}
+%
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \paragraph{Problems.}
+% \paragraph{Print Problems.}
 %
 % \macro{exf at problem}
 % Define options for |problem| environment:
 %    \begin{macrocode}
-\define at key{exf at problem}{points}{\exf at scanpoints\exf at points@given#1++&}
+\define at key{exf at problem}{points}{\exf at scanpoints\exf at problem@points#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):
+% \macro{printproblem}
+% Define |printproblem| environment:
 %    \begin{macrocode}
-\newenvironment{\exf at problemname}[1][]{%
+\newenvironment{printproblem}[1]{%
 %    \end{macrocode}
 % Start with new paragraph, set text style, add vspace:
 %    \begin{macrocode}
@@ -4879,11 +5253,11 @@
 %    \begin{macrocode}
   \exf at init@block{\exf at config@skipprobleminfo}%
   \def\problemtag{\csname the\exf at problemcounter\endcsname}%
-  \let\exf at points@given\@undefined%
+  \let\exf at problem@points\@undefined%
   \let\exf at label\@undefined%
   \global\let\exf at sollabel\@undefined%
   \let\exf at problem@points at total\@undefined%
-  \setkeys{exf at problem,exf at probleminfo}{#1}%
+  \setkeys{exf at problem,exf at probleminfo,exf at scanproblem}{#1}%
 %    \end{macrocode}
 % Process automatic and manual labels:
 %    \begin{macrocode}
@@ -4908,12 +5282,13 @@
 %    \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 tmp{exf at problempoints@\problemtag}%
-   \exf at exptwo\exf at scanpoints\exf at problem@points\exf at tmp++&%
+  \ifdefined\exf at problem@points%
+   \let\exf at problem@points at given\exf at empty%
+  \else%
+   \let\exf at problem@points at given\@undefined%
+   \ifcsname exf at problempoints@\problemtag\endcsname%
+    \exf at csdotwo\let\exf at tmp{exf at problempoints@\problemtag}%
+    \exf at exptwo\exf at scanpoints\exf at problem@points\exf at tmp++&%
   \fi\fi%
   \global\let\exf at prevpoints\exf at problem@points%
   \let\exf at problem@points at show\@undefined%
@@ -4929,9 +5304,9 @@
 % expand points into argument and remove points:
 %    \begin{macrocode}
   \exf at ifis\exf at pointsat{start}{\exf at outpoints{\exf at append@intro}%
-   {\exf at config@composepointspairstart}{\exf at problem@points at show}}%
+   {\exf at config@composepointspairstartproblem}{\exf at problem@points at show}}%
   \exf at ifis\exf at pointsat{start*}{\exf at outpoints{\exf at prepend@intro}%
-   {\exf at config@composepointspairstart}{\exf at problem@points at show}}%
+   {\exf at config@composepointspairstartproblem}{\exf at problem@points at show}}%
 %    \end{macrocode}
 % Insert hook code, set problem body style:
 %    \begin{macrocode}
@@ -5001,7 +5376,7 @@
 %    \end{macrocode}
 % Perform sanity checks on total points if given explicitly:
 %    \begin{macrocode}
-  \ifdefined\exf at points@given%
+  \ifdefined\exf at problem@points at given%
    \exf at warnmismatch{\exf at problemname}{\exf at problemcounter}%
     {\exf at problem@points at total}{\exf at problem@points}%
 %    \end{macrocode}
@@ -5026,12 +5401,12 @@
    \PackageWarning{exframe}{no points defined for \exf at problemname}%
   \fi\fi%
 %    \end{macrocode}
-% Solutions to subproblems must be declared within problem block:
+% Solutions to subproblems must be declared within problem environment:
 %    \begin{macrocode}
   \global\let\exf at prevsubprob\@undefined%
   \global\let\exf at prevsubprobhref\@undefined%
 %    \end{macrocode}
-% End paragraph and block:
+% End paragraph and environment:
 %    \begin{macrocode}
   \par\exf at close@block%
 %    \end{macrocode}
@@ -5068,8 +5443,209 @@
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \paragraph{Subproblems.}
+% \paragraph{Read Problem Environment.}
 %
+% \macro{exf at scanproblem}
+% Define options for |problem| environment:
+%    \begin{macrocode}
+\define at boolkey{exf at scanproblem}[exf at scanproblem@]{disable}[true]{}
+%    \end{macrocode}
+
+% \macro{exf at problem@direct}
+% Define direct output version of |problem| environment;
+% pass on to |printproblem| environment:
+%    \begin{macrocode}
+\newenvironment{exf at problem@direct}[1][]%
+ {\printproblem{#1}}{\endprintproblem\ignorespacesafterend}
+%    \end{macrocode}
+
+% \macro{exf at problem@scan}
+% \macro{exf at scanproblem}
+% Define scan version of |problem| environment;
+% use |\exf at scanblock| to properly parse optional argument
+% and pass on to |exf at scanproblem|:
+%    \begin{macrocode}
+\newenvironment{exf at problem@scan}%
+ {\exf at scanblock{\exf at scanproblem}}{\endexf at scanproblem}%
+\newenvironment{exf at scanproblem}[2]{%
+%    \end{macrocode}
+% Determine problem display:
+%    \begin{macrocode}
+  \exf at scanproblem@disablefalse%
+  \setkeys*{exf at scanproblem}{#1}%
+  \exf at config@insertproblemselect{#1}%
+%    \end{macrocode}
+% Write separator and |printproblem| environment to buffer:
+%    \begin{macrocode}
+  \ifexf at scanproblem@disable%
+   \def\exf at verbatim@process{\@gobble}%
+  \else%
+   \ifexf at lineno\exf at addline\exf at probbuf{\exf at linesep}%
+    \exf at addline\exf at probbuf{\exf at lineno}\fi%
+   \exf at addline\exf at probbuf%
+    {\@backslashchar begin{printproblem}{#1}}%
+   \def\exf at verbatim@process{\exf at append@buf\exf at probbuf}%
+  \fi%
+%    \end{macrocode}
+% Start verbatim processing:
+%    \begin{macrocode}
+  \exf at verbatim#2}%
+%    \end{macrocode}
+% End verbatim processing; close |printproblem| environment:
+%    \begin{macrocode}
+ {\exf at endverbatim%
+  \ifexf at scanproblem@disable\else%
+   \exf at addline\exf at probbuf{\@backslashchar end{printproblem}}%
+   \global\exf at probbuf@cleanfalse%
+  \fi%
+%    \end{macrocode}
+% Write buffer to file if output file open:
+%    \begin{macrocode}
+  \ifexf at probfile@open%
+   \exf at write@buf\exf at probfile\exf at probbuf%
+   \exf at clear@probbuf%
+  \fi%
+%    \end{macrocode}
+% Output buffer immediately:
+%    \begin{macrocode}
+  \ifexf at problemmanual\else%
+   \exf at source@buf\exf at probbuf%
+   \exf at clear@probbuf%
+  \fi%
+%    \end{macrocode}
+% Done:
+%    \begin{macrocode}
+  \ignorespacesafterend}
+%    \end{macrocode}
+
+% \macro{problem}
+% Define |problem| environment
+% (potentially using custom name)
+% to choose between direct and buffered version:
+%    \begin{macrocode}
+\newenvironment{\exf at problemname}%
+ {\ifexf at problembuf\let\exf at tmp\exf at problem@scan%
+  \else\let\exf at tmp\exf at problem@direct\fi%
+  \exf at tmp}%
+ {\ifexf at problembuf\let\exf at tmp\endexf at problem@scan%
+  \else\let\exf at tmp\endexf at problem@direct\fi%
+  \exf at tmp}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Problem Blocks}
+% \label{sec:imp-problems}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Block Handling.}
+%
+% \macro{\exf at problemstitle}
+% Compose the title for a problem block section:
+%    \begin{macrocode}
+\newcommand{\exf at problemstitle}{%
+%    \end{macrocode}
+% Check whether title is empty:
+%    \begin{macrocode}
+  \protected at edef\exf at problemstitleexp{\exf at config@composetitleproblems}%
+  \ifx\exf at problemstitleexp\exf at empty\else%
+%    \end{macrocode}
+% Output section line:
+%    \begin{macrocode}
+   \exf at section{\exf at config@skipproblemstitle}%
+    {\exf at config@styletitle\exf at config@styletitleproblems%
+     \exf at problemstitleexp}%
+   \exf at addcontentsline{\exf at config@toclevelproblems}%
+    {\exf at config@composetocproblems}%
+  \fi}
+%    \end{macrocode}
+
+% \macro{\exf at showproblemsin}
+% Output problem block intro:
+%    \begin{macrocode}
+\newcommand{\exf at showproblemsin}{%
+%    \end{macrocode}
+% Set problem body style; add vertical space; insert hook code:
+%    \begin{macrocode}
+  \par\exf at config@styletext\addvspace{\exf at config@skipproblemsabove}%
+  \exf at config@insertproblemsbefore}
+%    \end{macrocode}
+
+% \macro{\exf at showproblemsout}
+% Output problem block outro:
+%    \begin{macrocode}
+\newcommand{\exf at showproblemsout}{%
+%    \end{macrocode}
+% Insert hook code; close paragraph; add vertical space:
+%    \begin{macrocode}
+  \exf at config@insertproblemsafter%
+  \par\exf at config@styletext\addvspace{\exf at config@skipproblemsbelow}}
+%    \end{macrocode}
+
+% \macro{\exf at showproblems}
+% Output problem block in buffer:
+%    \begin{macrocode}
+\newcommand{\exf at showproblems}{%
+%    \end{macrocode}
+% Do nothing if buffer is empty (avoid titles):
+%    \begin{macrocode}
+  \ifexf at probbuf@clean\else\begingroup%
+%    \end{macrocode}
+% Execute output problem block intro:
+%    \begin{macrocode}
+   \exf at showproblemsin%
+   \exf at problemstitle%
+%    \end{macrocode}
+% Source and clear buffer:
+%    \begin{macrocode}
+   \exf at source@buf\exf at probbuf%
+   \exf at clear@probbuf%
+%    \end{macrocode}
+% Execute output problem block outro:
+%    \begin{macrocode}
+   \exf at showproblemsout%
+  \endgroup\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problems Buffer Interface.}
+%
+% \macro{\writeproblems}
+% Open a file |#1.prb| for writing problems;
+% default is present main file name:
+%    \begin{macrocode}
+\newcommand{\writeproblems}[1][\jobname]{%
+  \exf at close@probfile\exf at start@probfile{#1}}
+%    \end{macrocode}
+
+% \macro{\closeproblems}
+% Close problems output file (if open):
+%    \begin{macrocode}
+\newcommand{\closeproblems}{\exf at close@probfile}
+%    \end{macrocode}
+
+% \macro{\readproblems}
+% Read problems from file |#1.prb|;
+% default is present main file name;
+% switch layout and add heading:
+%    \begin{macrocode}
+\newcommand{\readproblems}[1][\jobname]{\exf at close@probfile%
+  \begingroup%
+   \exf at config@styletext\exf at config@styletextproblem%
+   \exf at problemstitle%
+   \input{#1\exf at config@extproblems}%
+  \endgroup}
+%    \end{macrocode}
+
+% \macro{\insertproblems}
+% Show problems buffer:
+%    \begin{macrocode}
+\newcommand{\insertproblems}{\exf at showproblems}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Subproblem Environment}
+% \label{sec:imp-subproblem}
+%
 % \macro{exf at subproblem}
 % Define options for |subproblem| environment:
 %    \begin{macrocode}
@@ -5115,6 +5691,14 @@
     \csname theH\exf at subproblemcounter\endcsname}%
   \fi%
 %    \end{macrocode}
+% Remeber points for display;
+% disable points display if desired:
+%    \begin{macrocode}
+  \let\exf at subproblem@points at show\@undefined%
+  \ifdefined\exf at subproblem@points%
+   \let\exf at subproblem@points at show\exf at subproblem@points\fi%
+  \exf at ifis\exf at subpointsat{off}{\let\exf at subproblem@points at show\@undefined}%
+%    \end{macrocode}
 % Add given points to problem total:
 %    \begin{macrocode}
   \ifdefined\exf at subproblem@points%
@@ -5129,17 +5713,13 @@
    \fi%
   \fi%
 %    \end{macrocode}
-% Disable points display if desired:
-%    \begin{macrocode}
-  \exf at ifis\exf at subpointsat{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 ifis\exf at subpointsat{start}{\exf at outpoints{\exf at append@intro}%
-   {\exf at config@composepointspairstart}{\exf at subproblem@points}}%
+   {\exf at config@composepointspairstartsubproblem}{\exf at subproblem@points at show}}%
   \exf at ifis\exf at subpointsat{start*}{\exf at outpoints{\exf at prepend@intro}%
-   {\exf at config@composepointspairstart}{\exf at subproblem@points}}%
+   {\exf at config@composepointspairstartsubproblem}{\exf at subproblem@points at show}}%
 %    \end{macrocode}
 % Insert hook code:
 %    \begin{macrocode}
@@ -5179,7 +5759,7 @@
 %    \begin{macrocode}
   \exf at ifis\exf at subpointsat{margin}{%
    \exf at outpoints{\exf at prepend@def\exf at introitem}%
-   {\exf at makepointsmargin}{\exf at subproblem@points}}%
+   {\exf at makepointsmargin}{\exf at subproblem@points at show}}%
 %    \end{macrocode}
 % Write out opening line:
 %    \begin{macrocode}
@@ -5193,7 +5773,7 @@
 %    \begin{macrocode}
  {\exf at ifis\exf at subpointsat{end}{\showpoints}%
 %    \end{macrocode}
-% End paragraph and block:
+% End paragraph and environment:
 %    \begin{macrocode}
   \par\exf at close@block%
 %    \end{macrocode}
@@ -5222,6 +5802,10 @@
   \ignorespacesafterend}
 %    \end{macrocode}
 
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Solution Environment}
+% \label{sec:imp-solution}
+%
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Print Solutions.}
 %
@@ -5240,7 +5824,7 @@
 
 % \macro{printsolution}
 % Define |printsolution| environment
-% to display a previously read |solution| block;
+% to display a previously read |solution| environment;
 % this works analogously to |problem| and |subproblem|:
 %    \begin{macrocode}
 \newenvironment{printsolution}[1]{%
@@ -5262,12 +5846,14 @@
    \let\theHequation\theHexf at solutionequation%
   \fi%
 %    \end{macrocode}
-% Start a block, initialise variables, process arguments:
+% Start a group, initialise variables, process arguments:
 %    \begin{macrocode}
   \begingroup%
+  \def\exf at in@solution{}%
   \def\exf at solprob{}%
   \def\exf at solsubprob{}%
   \let\exf at label\@undefined%
+  \let\exf at solution@points\@undefined%
   \let\exf at solution@points at total\@undefined%
   \def\exf at solhref{}%
   \exf at init@block{\exf at config@skipsolutioninfo}%
@@ -5283,6 +5869,22 @@
 %    \begin{macrocode}
   \ifdefined\exf at label\label{\exf at label}\fi%
 %    \end{macrocode}
+% Remeber points for display;
+% disable points display if desired:
+%    \begin{macrocode}
+  \let\exf at solution@points at show\@undefined%
+  \ifdefined\exf at solution@points%
+   \let\exf at solution@points at show\exf at solution@points\fi%
+  \exf at ifis\exf at solpointsat{off}{\let\exf at solution@points at show\@undefined}%
+%    \end{macrocode}
+% Display points in opening line if desired;
+% expand points into argument and remove points:
+%    \begin{macrocode}
+  \exf at ifis\exf at solpointsat{start}{\exf at outpoints{\exf at append@intro}%
+   {\exf at config@composepointspairstartsolution}{\exf at solution@points at show}}%
+  \exf at ifis\exf at solpointsat{start*}{\exf at outpoints{\exf at prepend@intro}%
+   {\exf at config@composepointspairstartsolution}{\exf at solution@points at show}}%
+%    \end{macrocode}
 % Insert hook code, set solution body style:
 %    \begin{macrocode}
   \exf at config@insertsolutioninfo%
@@ -5325,7 +5927,7 @@
      \fi\exf at config@composeitemsolutionsep}%
    \fi%
 %    \end{macrocode}
-% Set item label up depending on problem or subproblem:
+% Set item label depending on problem or subproblem:
 %    \begin{macrocode}
    \ifx\exf at solsubprob\exf at empty%
     \protected at edef\exf at solution@item%
@@ -5344,6 +5946,13 @@
     \exf at config@composeitemproblemsep}}%
   \fi%
 %    \end{macrocode}
+% Write points into margin if desired;
+% expand points into argument and remove points:
+%    \begin{macrocode}
+  \exf at ifis\exf at solpointsat{margin}{%
+   \exf at outpoints{\exf at prepend@def\exf at introitem}%
+   {\exf at makepointsmargin}{\exf at solution@points at show}}%
+%    \end{macrocode}
 % Write out opening line:
 %    \begin{macrocode}
   \exf at open@block{\exf at config@skipsolutiontitle}%
@@ -5354,10 +5963,11 @@
 %    \end{macrocode}
 % End environment, show points if desired, perform sanity check:
 %    \begin{macrocode}
- {\exf at warnmismatch{\exf at solutionname}{\exf at solutioncounter}%
+ {\exf at ifis\exf at solpointsat{end}{\showpoints}%
+  \exf at warnmismatch{\exf at solutionname}{\exf at solutioncounter}%
    {\exf at solution@points at total}{\exf at solution@points}%
 %    \end{macrocode}
-% End paragraph and block:
+% End paragraph and envionment:
 %    \begin{macrocode}
   \par\exf at close@block%
 %    \end{macrocode}
@@ -5383,7 +5993,7 @@
 %    \end{macrocode}
 
 % \macro{\solutionssection}
-% Define a section for a problem within a block with multiple solutions:
+% Define a section for a problem within a solution block:
 %    \begin{macrocode}
 \newcommand{\solutionssection}[1]{\begingroup%
 %    \end{macrocode}
@@ -5397,56 +6007,34 @@
   \setkeys{exf at solution}{#1}%
 %    \end{macrocode}
 % Select title (and table of contents entry)
-% corresponding to multiple problems vs. single problem:
+% 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 ifis\exf at solutionbelow{problem}{\let\exf at composetitle%
     \exf at config@composetitlesolutionsproblemsingle}%
   \exf at ifis\exf at solutionbelow{problem*}{\let\exf at composetitle%
     \exf at config@composetitlesolutionsproblemsingle}%
+  \def\exf at solutionstoc{\exf at addcontentsline{\exf at config@toclevelsolution}%
+    {\exf at config@composetocsolution{\exf at solprob}{\exf at solprobtitle}}}%
 %    \end{macrocode}
 % Write section line:
 %    \begin{macrocode}
+  \addvspace{\exf at config@skipsolutionsproblemabove}%
   \exf at solutionssection{\exf at config@styletitlesolutionsproblem}%
    {\exf at composetitle{\exf at solprob}{\exf at solprobtitle}}%
-   {\exf at config@skipsolutionsproblem}%
+   {\exf at config@skipsolutionsproblemtitle}%
    {\exf at solutionstoc}{\exf at label}{\exf at solhref}%
   \endgroup}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \paragraph{Read Solution Block to Buffer.}
+% \paragraph{Read Solution Environment.}
 %
-% \macro{solution}
-% Define |solution| environment (potentially using custom name);
-% pass to |exf at scansolution| environment via
-% |\exf at scanblock| mechanism;
-% redefine |\exf at scanblock| in |solutionbelow=here*| mode:
-%    \begin{macrocode}
-\newenvironment{\exf at solutionname}%
-  {\exf at ifis\exf at solutionbelow{here*}{%
-    \newcommand{\exf at scanblockplain}[1][]{\exf at scansolution{##1}{}}%
-    \def\exf at scanblock##1{\exf at scanblockplain}}%
-   \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 ifis\exf at solutionbelow{here}{\showpoints}%
-  \exf at ifis\exf at solutionbelow{here*}{\showpoints}%
-  \global\exf at bufcleanfalse%
-%    \end{macrocode}
+% \macro{\exf at process@solnewsec}
 % If this is the first solution within a new section,
-% display section heading:
+% write section heading to buffer:
 %    \begin{macrocode}
+\newcommand{\exf at process@solnewsec}{%
   \ifdefined\exf 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%
@@ -5453,25 +6041,24 @@
     \ifdefined\exf at prevprobhref,href={\exf at prevprobhref}\fi%
     \ifdefined\exf at sollabel,label={\exf at sollabel}\fi}%
    \exf at ifis\exf at solutionbelow{here}{\let\exf at probarg\@undefined}%
-   \exf at ifis\exf at solutionbelow{here*}{\let\exf at probarg\@undefined}%
    \exf at ifis\exf at solutionbelow{subproblem}{\let\exf at probarg\@undefined}%
    \exf at ifis\exf at solutionbelow{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{}%
+    \ifexf at lineno\exf at addline\exf at solbuf{\exf at linesep}%
+     \exf at addline\exf at solbuf{\exf at lineno}\fi%
+    \exf at addline\exf at solbuf{\@backslashchar solutionssection{\exf at probarg}}%
+    \exf at addline\exf at solbuf{}%
    \fi%
    \global\let\exf at problem@solnewsec\@undefined%
-  \fi%
+  \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}
+
+% \macro{\exf at process@solnewsec}
 % Declare additional arguments to |printsolution|
 % to describe corresponding problem and tags:
 %    \begin{macrocode}
-  \def\exf at subprobarg{%
+\newcommand{\exf at generate@solprobarg}{%
+  \edef\exf at solprobarg{%
     \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%
@@ -5483,48 +6070,76 @@
     \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%
+  \global\let\exf at prevpoints\@undefined}%
 %    \end{macrocode}
-% In |here*| mode, output solution immediately;
-% overwrite verbatim macros to display solution:
+
+% \macro{exf at solution@direct}
+% Define direct output version of |solution| environment;
+% pass on to |printsolution| environment:
 %    \begin{macrocode}
-  \exf at ifis\exf at solutionbelow{here*}{%
-   \def\exf at verbatim{\exf at clearbuf\begingroup%
-    \edef\exf at subprobarg{\exf at subprobarg}%
-    \exf at showsolutionsin{\exf at config@composetitlesolutionsingle}%
-    \exf at exptwo\printsolution{\exf at subprobarg#1}}%
-   \def\exf at endverbatim{\endprintsolution\exf at showsolutionsout\endgroup}}%
+\newenvironment{exf at solution@direct}[1][]%
+ {\showpoints%
+  \global\let\exf at problem@solnewsec\@undefined%
+  \exf at generate@solprobarg%
+  \exf at showsolutionsin%
+  \let\exf at composetitle\exf at config@composetitlesolutionsingle%
+  \exf at exptwo\printsolution{\exf at solprobarg#1}}%
+ {\endprintsolution%
+  \exf at showsolutionsout%
+  \ignorespacesafterend}%
 %    \end{macrocode}
-% Verbatim read block to buffer:
+
+% \macro{exf at solution@scan}
+% \macro{exf at scansolution}
+% Define scan version of |solution| environment;
+% use |\exf at scanblock| to properly parse optional argument
+% and pass on to |exf at scansolution|:
 %    \begin{macrocode}
+\newenvironment{exf at solution@scan}%
+ {\exf at scanblock{\exf at scansolution}}{\endexf at scansolution}%
+\newenvironment{exf at scansolution}[2]{%
+%    \end{macrocode}
+% If solution is to be displayed immediately,
+% make sure to display points first;
+% insert solution section heading in buffer;
+% compose additional arguments to |printsolution|:
+%    \begin{macrocode}
+  \exf at ifis\exf at solutionbelow{here}{\showpoints}%
+  \exf at process@solnewsec%
+  \exf at generate@solprobarg%
+%    \end{macrocode}
+% Write separator and |printsolution| environment to buffer:
+%    \begin{macrocode}
+  \ifexf at lineno\exf at addline\exf at solbuf{\exf at linesep}%
+   \exf at addline\exf at solbuf{\exf at lineno}\fi%
+  \exf at addline\exf at solbuf%
+   {\@backslashchar begin{printsolution}{\exf at solprobarg#1}}%
+%    \end{macrocode}
+% Start verbatim processing:
+%    \begin{macrocode}
+  \def\exf at verbatim@process{\exf at append@buf\exf at solbuf}%
   \exf at verbatim#2}%
 %    \end{macrocode}
-% End environment; stop reading buffer:
+% End verbatim processing; close |printsolution| environment:
 %    \begin{macrocode}
  {\exf at endverbatim%
+  \exf at addline\exf at solbuf{\@backslashchar end{printsolution}}%
+  \global\exf at solbuf@cleanfalse%
 %    \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%
+  \ifexf at solfile@open%
+   \exf at write@buf\exf at solfile\exf at solbuf%
+   \exf at clear@solbuf%
   \fi%
 %    \end{macrocode}
 % Drop buffer if solutions not to be displayed:
 %    \begin{macrocode}
-  \ifsolutions\else\exf at clearbuf\fi%
+  \ifsolutions\else\exf at clear@solbuf\fi%
 %    \end{macrocode}
 % Display solution immediately in various cases:
 %    \begin{macrocode}
@@ -5546,11 +6161,29 @@
   \ignorespacesafterend}
 %    \end{macrocode}
 
+% \macro{solution}
+% Define |solution| environment
+% (potentially using custom name)
+% to choose between direct and buffered version:
+%    \begin{macrocode}
+\newenvironment{\exf at solutionname}%
+ {\ifexf at solutionbuf\let\exf at tmp\exf at solution@scan%
+  \else\let\exf at tmp\exf at solution@direct\fi%
+  \exf at tmp}%
+ {\ifexf at solutionbuf\let\exf at tmp\endexf at solution@scan%
+  \else\let\exf at tmp\endexf at solution@direct\fi%
+  \exf at tmp}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Solution Blocks}
+% \label{sec:imp-solutions}
+%
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Solution Block Handling.}
 %
 % \macro{\exf at solutionssection}
-% Output solutions section:
+% Output solution block section:
 %    \begin{macrocode}
 \newcommand{\exf at solutionssection}[6]{%
 %    \end{macrocode}
@@ -5576,7 +6209,7 @@
 %    \end{macrocode}
 
 % \macro{\exf at solutionstitle}
-% Compose the title for a solution section:
+% Compose the title for a solution block:
 %    \begin{macrocode}
 \newcommand{\exf at solutionstitle}{\exf at solutionssection%
   {\exf at config@styletitlesolutions}{%
@@ -5586,51 +6219,49 @@
 %    \end{macrocode}
 
 % \macro{\exf at showsolutionsin}
-% Output solutions intro:
+% Output solution block intro:
 %    \begin{macrocode}
-\newcommand{\exf at showsolutionsin}[1]{%
+\newcommand{\exf at showsolutionsin}{%
 %    \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}
+  \exf at config@insertsolutionsbefore}
 %    \end{macrocode}
 
 % \macro{\exf at showsolutionsout}
-% Output solutions outro:
+% Output solution block outro:
 %    \begin{macrocode}
 \newcommand{\exf at showsolutionsout}{%
 %    \end{macrocode}
-% Ignore most recent skip; insert hook code;
-% close paragraph; add vertical space:
+% 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}}
+  \par\exf at config@styletext\addvspace{\exf at config@skipsolutionsbelow}}
 %    \end{macrocode}
 
 % \macro{\exf at showsolutions}
-% Output solutions in buffer:
+% Output solution block 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%
+  \ifexf at solbuf@clean\else\begingroup%
 %    \end{macrocode}
-% Execute output solutions intro:
+% Execute output solution block intro:
 %    \begin{macrocode}
-   \exf at showsolutionsin{#1}%
+   \exf at showsolutionsin%
+   \let\exf at composetitle#1%
    #2%
 %    \end{macrocode}
 % Source and clear buffer:
 %    \begin{macrocode}
-   \exf at sourcebuf%
-   \exf at clearbuf%
+   \exf at source@buf\exf at solbuf%
+   \exf at clear@solbuf%
 %    \end{macrocode}
-% Execute output solutions outro:
+% Execute output solution block outro:
 %    \begin{macrocode}
    \exf at showsolutionsout%
   \endgroup\fi}
@@ -5643,13 +6274,14 @@
 % 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}}
+\newcommand{\writesolutions}[1][\jobname]{%
+  \exf at close@solfile\exf at start@solfile{#1}}
 %    \end{macrocode}
 
 % \macro{\closesolutions}
-% Close output file (if open):
+% Close solutions output file (if open):
 %    \begin{macrocode}
-\newcommand{\closesolutions}{\exf at closefile}
+\newcommand{\closesolutions}{\exf at close@solfile}
 %    \end{macrocode}
 
 % \macro{\readsolutions}
@@ -5657,17 +6289,17 @@
 % default is present main file name;
 % switch layout and add heading:
 %    \begin{macrocode}
-\newcommand{\readsolutions}[1][\jobname]{\exf at closefile%
+\newcommand{\readsolutions}[1][\jobname]{\exf at close@solfile%
   \ifsolutions\begingroup%
    \exf at config@styletext\exf at config@styletextsolution%
-   \let\exf at config@composetitlesolution\exf at config@composetitlesolutionmulti%
+   \let\exf at composetitle\exf at config@composetitlesolutionmulti%
    \exf at solutionstitle%
-   \input{#1.sol}%
+   \input{#1\exf at config@extsolutions}%
   \endgroup\fi}
 %    \end{macrocode}
 
 % \macro{\insertsolutions}
-% Show solution buffer:
+% Show solutions buffer:
 %    \begin{macrocode}
 \newcommand{\insertsolutions}{\exf at showsolutions%
   {\exf at config@composetitlesolutionmulti}{\exf at solutionstitle}}

Modified: trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty	2019-06-16 22:04:20 UTC (rev 51387)
+++ trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty	2019-06-16 22:04:41 UTC (rev 51388)
@@ -17,7 +17,7 @@
 %% version 2005/12/01 or later.
 %% 
 \NeedsTeXFormat{LaTeX2e}[1996/12/01]
-\ProvidesPackage{exframe}[2019/05/01 v3.2 Framework for Exercise Problems]
+\ProvidesPackage{exframe}[2019/06/15 v3.3 Framework for Exercise Problems]
 
 \RequirePackage{verbatim}
 \RequirePackage{xkeyval}
@@ -83,6 +83,9 @@
 \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]{}
+\define at boolkey{exf at setup}[exf@]{solutionbuf}[true]{}
+\exf at solutionbuftrue
+\define at boolkey{exf at setup}[exf@]{problembuf}[true]{}
 
 \ProcessOptionsX<exframe.sty,exf at setup>
 
@@ -123,6 +126,7 @@
 \exerciseconfig{styletitlesolution}{}
 \exerciseconfig{styletitlesolutionsproblem}{\small}
 \exerciseconfig{styletitlesolutions}{\normalsize}
+\exerciseconfig{styletitleproblems}{\Large}
 
 \exerciseconfig{skipproblemabove}{3.25ex plus 1ex minus 1.5ex}
 \exerciseconfig{skipproblembelow}{3pt plus 1pt minus 1pt}
@@ -145,9 +149,15 @@
 
 \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{skipsolutionsproblemabove}{1.0ex plus 0ex minus 0.5ex}
+\exerciseconfig{skipsolutionsproblemtitle}{1.0ex plus 0ex minus 0.5ex}
+\exerciseconfig{skipsolutionsproblem}{\exf at config@skipsolutionsproblemtitle}
 \exerciseconfig{skipsolutionstitle}{1.0ex plus 0ex minus 0.5ex}
 
+\exerciseconfig{skipproblemsabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipproblemsbelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipproblemstitle}{1.0ex plus 0ex minus 0.5ex}
+
 \exerciseconfig{insertsheettitle}{\centerline{\getsheetdata{title}}}
 \exerciseconfig{insertsheetclearpage}{\exercisecleardoublepage}
 \exerciseconfig{insertsheetbefore}{}
@@ -154,10 +164,13 @@
 \exerciseconfig{insertsheetafter}{}
 \exerciseconfig{insertsolutionsbefore}{}
 \exerciseconfig{insertsolutionsafter}{}
+\exerciseconfig{insertproblemsbefore}{}
+\exerciseconfig{insertproblemsafter}{}
 \exerciseconfig{insertproblembefore}{}
 \exerciseconfig{insertproblemafter}{}
 \exerciseconfig{insertproblemsolution}{}
 \exerciseconfig{insertprobleminfo}{}
+\exerciseconfig{insertproblemselect}[1]{}
 \exerciseconfig{insertsubproblembefore}{}
 \exerciseconfig{insertsubproblemafter}{}
 \exerciseconfig{insertsubprobleminfo}{}
@@ -198,8 +211,12 @@
   {\getexerciseconfig{composetocproblem}{#1}{#2}}
 \exerciseconfig{composetitlesolutions}%
   {\getexerciseconfig{termsolutions}}
+\exerciseconfig{composetitleproblems}%
+  {\getexerciseconfig{termproblems}}
 \exerciseconfig{composetocsolutions}%
   {\getexerciseconfig{composetitlesolutions}}
+\exerciseconfig{composetocproblems}%
+  {\getexerciseconfig{composetitleproblems}}
 \exerciseconfig{composetitlesolutionsproblemsingle}[2]%
   {\getexerciseconfig{termsolution}}
 \exerciseconfig{composetitlesolutionsproblemmulti}[2]%
@@ -250,6 +267,18 @@
   \ifdim#2pt=0pt\getexerciseconfig{composepointsawardalt}{#1}{#3}\else%
   (\getexerciseconfig{composepointspair}{#1}{#2}*%
    \exerciseifnotempty{#3}{; #3})\fi}
+\exerciseconfig{composepointspairbodyproblem}[2]{%
+  \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairbodysubproblem}[2]{%
+  \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairbodysolution}[2]{%
+  \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairstartproblem}[2]{%
+  \getexerciseconfig{composepointspairstart}{#1}{#2}}
+\exerciseconfig{composepointspairstartsubproblem}[2]{%
+  \getexerciseconfig{composepointspairstart}{#1}{#2}}
+\exerciseconfig{composepointspairstartsolution}[2]{%
+  \getexerciseconfig{composepointspairstart}{#1}{#2}}
 
 \exerciseconfig{insertpointsmargin}[1]{\marginpar{\footnotesize #1}}
 
@@ -272,9 +301,13 @@
 
 \exerciseconfig{toclevelsheet}{}
 \exerciseconfig{toclevelproblem}{}
+\exerciseconfig{toclevelproblems}{}
 \exerciseconfig{toclevelsolution}{}
 \exerciseconfig{toclevelsolutions}{}
 
+\exerciseconfig{extsolutions}{.sol}
+\exerciseconfig{extproblems}{.prb}
+
 \newcommand{\defexercisestylearg}[3][]{%
   \def\exf at tmp{#1}\ifx\exf at tmp\exf at empty%
    \define at key{exf at style}{#2}{#3}\else%
@@ -285,20 +318,31 @@
    {\csname ifexf at style@#1\endcsname\csname exf at style@code@#1\endcsname\fi}}
 \newcommand{\exercisestyle}[1]{\exf at expsetkeys{exf at style}{#1}}
 
+\define at boolkey{exf at style}[exf@]{problemmanual}[true]{}
+\exf at problemmanualfalse
 \def\exf at solutionbelow{subproblem}
 \define at choicekey{exf at style}{solutionbelow}%
-  {here,here*,subproblem,subproblem*,problem,problem*,sheet,manual}%
-  {\ifexf at infile\else\def\exf at solutionbelow{#1}\fi}
+  {here,subproblem,subproblem*,problem,problem*,sheet,manual}%
+  {\ifexf at solfile@open\else\gdef\exf at solutionbelow{#1}\fi}
 \defexercisestyle{sheetequation}{}
 \defexercisestyle{problemequation}{}
 \defexercisestyle{solutionequation}{}
 \exf at style@solutionequationtrue
 \def\exf at pointsat{start}
+\define at choicekey{exf at style}{problempointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at pointsat{#1}}
 \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}{subproblempointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at subpointsat{#1}}
 \define at choicekey{exf at style}{subpointsat}%
   {start,start*,margin,end,manual,off}{\def\exf at subpointsat{#1}}
+\def\exf at solpointsat{off}
+\define at choicekey{exf at style}{solutionpointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at solpointsat{#1}}
+\define at choicekey{exf at style}{solpointsat}%
+  {start,start*,margin,end,manual,off}{\def\exf at solpointsat{#1}}
 \defexercisestylearg{problemby}{\exf at numberproblemwithin{#1}}
 \defexercisestylearg{equationby}{\exf at numberequationwithin{#1}}
 \defexercisestyle{pagebysheet}{%
@@ -310,7 +354,7 @@
 \defexercisestyle{equationbysheet}%
   {\exf at numberequationwithin{\exf at sheetcounter}}
 \defexercisestyle{fracpoints}%
-  {\exerciseconfig{composepointsnum}[1]{\protect\exf at nicefrac{##1}}}
+  {\exerciseconfig{composepointsnum}[1]{\protect\showfracpoints{##1}}}
 \defexercisestylearg[true]{twoside}{\exercisesetup{twoside={#1}}}
 
 \ifexf at extstyle
@@ -325,7 +369,8 @@
   \exerciseconfigappend{styletextproblem}{\color[gray]{0.2}}}
 \defexercisestyle{solutionsep}{%
   \exerciseconfig{insertsolutionsbefore}{\hrule\nopagebreak[3]\vspace{0.5ex}}%
-  \exerciseconfig{insertsolutionsafter}{\nopagebreak[3]\vspace{1.0ex}\hrule}}
+  \exerciseconfig{insertsolutionsafter}%
+   {\removelastskip\nopagebreak[3]\vspace{1.0ex}\hrule}}
 \defexercisestyle{plainheader}{%
   \exerciseconfig{styleheadertitle}{\Large\bfseries}%
   \exerciseconfig{styleheadercourse}{\sffamily}%
@@ -386,6 +431,7 @@
   \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{\setsheetdata}[1]{\setkeys{exf at sheet}{#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}
@@ -407,6 +453,7 @@
   \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{\setproblemdata}[1]{\setkeys{exf at problem,exf at scanproblem}{#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}
@@ -544,10 +591,12 @@
   \def\theHexf at solutionequation%
    {\csname theH#1\endcsname.sol.\arabic{equation}}}
 
-\newif\ifexf at infile\exf at infilefalse
-\newwrite\exf at out
+\newif\ifexf at solfile@open\exf at solfile@openfalse
+\newif\ifexf at probfile@open\exf at probfile@openfalse
+\newwrite\exf at solfile
+\newwrite\exf at probfile
 
-\newcommand{\exf at writeline}[1]{\immediate\write\exf at out{#1}}
+\newcommand{\exf at writeline}[2]{\immediate\write#1{#2}}
 
 \newcommand{\exf at linesep}%
   {\@percentchar---------------------------------------}
@@ -555,46 +604,69 @@
   \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}%
+\newcommand{\exf at start@solfile}[1]{%
+  \ifexf at solfile@open\else%
+   \exercisestyle{solutionbelow=manual}%
+   \global\exf at solfile@opentrue%
    \edef\exf at tmp{#1}%
-   \immediate\openout\exf at out\exf at tmp.sol%
-   \exf at writeline{\@percentchar%
+   \immediate\openout\exf at solfile\exf at tmp\exf at config@extsolutions\relax%
+   \exf at writeline\exf at solfile{\@percentchar%
     generated from file `\jobname' by exframe.sty}%
-   \ifexf at lineno\exf at writeline{\exf at lineno}\fi%
-   \exf at writeline{}%
+   \ifexf at lineno\exf at writeline\exf at solfile{\exf at lineno}\fi%
+   \exf at writeline\exf at solfile{}%
   \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%
+\newcommand{\exf at close@solfile}{%
+  \ifexf at solfile@open%
+   \ifexf at lineno\exf at writeline\exf at solfile{\exf at linesep}%
+    \exf at writeline\exf at solfile{\exf at lineno}\fi%
+   \exf at writeline\exf at solfile{\@backslashchar endinput}%
+   \immediate\closeout\exf at solfile%
+   \global\exf at solfile@openfalse%
   \fi}
 
-\AtEndDocument{\exf at closefile}
+\newcommand{\exf at start@probfile}[1]{%
+  \ifexf at probfile@open\else%
+   \global\exf at probfile@opentrue%
+   \edef\exf at tmp{#1}%
+   \immediate\openout\exf at probfile\exf at tmp\exf at config@extproblems\relax%
+   \exf at writeline\exf at probfile{\@percentchar%
+    generated from file `\jobname' by exframe.sty}%
+   \ifexf at lineno\exf at writeline\exf at probfile{\exf at lineno}\fi%
+   \exf at writeline\exf at probfile{}%
+  \fi}
 
-\newtoks\exf at buf
-\newif\ifexf at bufclean\exf at bufcleantrue
+\newcommand{\exf at close@probfile}{%
+  \ifexf at probfile@open%
+   \ifexf at lineno\exf at writeline\exf at probfile{\exf at linesep}%
+    \exf at writeline\exf at probfile{\exf at lineno}\fi%
+   \exf at writeline\exf at probfile{\@backslashchar endinput}%
+   \immediate\closeout\exf at probfile%
+   \global\exf at probfile@openfalse%
+  \fi}
 
-\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}}}
+\AtEndDocument{\exf at close@solfile\exf at close@probfile}
 
-\def\exf at sourcebuf{\exf at exptwo\scantokens{\the\exf at buf}}
-\def\exf at writebuf{\exf at writeline{\the\exf at buf}}
+\newtoks\exf at solbuf
+\newtoks\exf at probbuf
+\newif\ifexf at solbuf@clean\exf at solbuf@cleantrue
+\newif\ifexf at probbuf@clean\exf at probbuf@cleantrue
+\def\exf at clear@solbuf{\global\exf at solbuf@cleantrue\global\exf at solbuf={}}
+\def\exf at clear@probbuf{\global\exf at probbuf@cleantrue\global\exf at probbuf={}}
 
+\def\exf at append@buf#1#2{\global#1=\expandafter{\the#1#2}}
+\def\exf at addline#1#2{{\protected at edef\exf at tmp{#2}%
+  \exf at exparg{\exf at append@buf#1}{\exf at tmp^^J}}}
+\def\exf at source@buf#1{\exf at exptwo\scantokens{\the#1}}
+\def\exf at write@buf#1#2{\exf at writeline#1{\the#2}}
+
 \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}}%
+  \def\verbatim at processline{\exf at exptwo\exf at verbatim@process%
+   {\the\verbatim at line^^J}}%
   \verbatim at start}
 
 \newcommand{\exf at endverbatim}{\@esphack\endgroup}
@@ -645,6 +717,15 @@
   \exf at exptwo\exf at scanpoints\exf at tmp\exf at tmp++&%
   \expandafter#1\exf at tmp}
 
+\newcommand{\switchpoints}[5]{\edef\exf at tmp{#5}%
+  \exf at exptwo\exf at scanpoints\exf at tmp\exf at tmp++&%
+  \expandafter\exf at switchpoints\exf at tmp{#1}{#2}{#3}{#4}}
+\newcommand{\exf at switchpoints}[6]{%
+  \ifdim#2pt=0pt\ifdim#1pt=0pt\def\exf at tmp##1##2{#6}%
+   \else\def\exf at tmp##1##2{#3}\fi%
+  \else\ifdim#1pt=0pt\def\exf at tmp##1##2{#4}%
+   \else\def\exf at tmp##1##2{#5}\fi\fi\exf at tmp{#1}{#2}}
+
 \newcommand{\exf at makepointsmargin}[2]{%
   \exf at config@insertpointsmargin{\exf at config@composepointspairmargin{#1}{#2}}}
 
@@ -670,7 +751,7 @@
 \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]{%
+\newcommand{\showfracpoints}[1]{%
   \edef\exf at tmp{#1}%
   \expandafter\exf at splitsign\exf at tmp--&%
   \expandafter\exf at splitdecimal\exf at splitnum..&%
@@ -678,17 +759,17 @@
   \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%
+  \ifnum\exf at splitdec=5\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{2}}\fi%
+  \ifnum\exf at splitdec=25\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{4}}\fi%
+  \ifnum\exf at splitdec=75\def\exf at tmp{\exf at config@frac{\exf at splitint}{3}{4}}\fi%
+  \ifnum\exf at splitdec=125\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{8}}\fi%
+  \ifnum\exf at splitdec=375\def\exf at tmp{\exf at config@frac{\exf at splitint}{3}{8}}\fi%
+  \ifnum\exf at splitdec=625\def\exf at tmp{\exf at config@frac{\exf at splitint}{5}{8}}\fi%
+  \ifnum\exf at splitdec=875\def\exf at tmp{\exf at config@frac{\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]{%
+\newcommand{\exf at config@frac}[3]{%
   \ifnum#1=0\else#1\fi%
   \ifnum#2=0\else$%
    ^{\exf at text{#2}}%
@@ -702,8 +783,11 @@
 \newcommand{\exf at writesheetpoints}[2]%
   {\immediate\write\@auxout{\string\exf at notesheetpoints{\sheettag}%
    {\exf at formatpoints{#1}{#2}}}}
-\newcommand{\getsheetpoints}[1]{\ifcsname exf at sheetpoints@#1\endcsname%
-  \csname exf at sheetpoints@#1\endcsname\else 0\fi}
+\newcommand{\getsheetpoints}[1]{\if&#1&%
+   \ifdefined\exf at sheet@points%
+    \expandafter\exf at formatpoints\exf at sheet@points\else 0\fi%
+  \else\ifcsname exf at sheetpoints@#1\endcsname%
+   \csname exf at sheetpoints@#1\endcsname\else 0\fi\fi}
 
 \newcommand{\exf at noteproblempoints}[2]{%
   \exf at csdo\gdef{exf at problempoints@#1}{#2}}
@@ -712,15 +796,24 @@
 \newcommand{\exf at writeproblempoints}[2]%
   {\immediate\write\@auxout{\string\exf at noteproblempoints{\problemtag}%
    {\exf at formatpoints{#1}{#2}}}}
-\newcommand{\getproblempoints}[1]{\ifcsname exf at problempoints@#1\endcsname%
-  \csname exf at problempoints@#1\endcsname\else 0\fi}
+\newcommand{\getproblempoints}[1]{\if&#1&%
+   \ifdefined\exf at problem@points%
+    \expandafter\exf at formatpoints\exf at problem@points\else 0\fi%
+  \else\ifcsname exf at problempoints@#1\endcsname%
+   \csname exf at problempoints@#1\endcsname\else 0\fi\fi}
+\newcommand{\getsubproblempoints}[1]{\if&#1&%
+   \ifdefined\exf at subproblem@points%
+    \expandafter\exf at formatpoints\exf at subproblem@points\else 0\fi%
+  \else 0\fi}
 
 \newcommand{\showpoints}{%
-  \ifdefined\exf at in@subproblem\exf at outpoints{\exf at ensuretext}%
-   {\exf at config@composepointspairbody}{\exf at subproblem@points}%
+  \ifdefined\exf at in@solution\exf at outpoints{\exf at ensuretext}%
+   {\exf at config@composepointspairbodysolution}{\exf at solution@points at show}%
+  \else\ifdefined\exf at in@subproblem\exf at outpoints{\exf at ensuretext}%
+   {\exf at config@composepointspairbodysubproblem}{\exf at subproblem@points at show}%
   \else\ifdefined\exf at in@problem\exf at outpoints{\exf at ensuretext}%
-   {\exf at config@composepointspairbody}{\exf at problem@points at show}%
-  \fi\fi}
+   {\exf at config@composepointspairbodyproblem}{\exf at problem@points at show}%
+  \fi\fi\fi}
 
 \newcommand{\exf at awardpointsalt}[2][]{\exf at scanpoints\exf at tmp#2++&%
   \exf at exptwo\exf at ensuretext{%
@@ -732,7 +825,12 @@
    \expandafter\exf at config@composepointspairaward\exf at tmp{#1}}}
 \newcommand{\awardpoints}{\@ifstar\exf at awardpointsalt\exf at awardpointsreg}
 
-\define at key{exf at sheet}{points}{\exf at scanpoints\exf at points@given#1++&}
+\newcommand{\getsolutionpoints}[1]{\if&#1&%
+   \ifdefined\exf at solution@points%
+    \expandafter\exf at formatpoints\exf at solution@points\else 0\fi%
+  \else 0\fi}
+
+\define at key{exf at sheet}{points}{\exf at scanpoints\exf at sheet@points#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}}
@@ -746,7 +844,7 @@
    \let\theequation\theexf at sheetequation%
    \let\theHequation\theHexf at sheetequation%
   \fi%
-  \let\exf at points@given\@undefined%
+  \let\exf at sheet@points\@undefined%
   \def\sheettag{\csname the\exf at sheetcounter\endcsname}%
   \let\exf at sheet@points at total\@undefined%
   \let\exf at label\@undefined%
@@ -753,12 +851,13 @@
   \setkeys{exf at sheet}{#1}%
   \ifexf at autolabelsheet\label{\exf at config@labelsheet{\sheettag}}\fi%
   \ifdefined\exf at label\label{\exf at label}\fi%
-  \let\exf at sheet@points\@undefined%
-  \ifdefined\exf at points@given%
-   \let\exf at sheet@points\exf at points@given%
-  \else\ifcsname exf at sheetpoints@\sheettag\endcsname%
-   \exf at csdotwo\let\exf at tmp{exf at sheetpoints@\sheettag}%
-   \exf at exptwo\exf at scanpoints\exf at sheet@points\exf at tmp++&%
+  \ifdefined\exf at sheet@points%
+   \let\exf at sheet@points at given\exf at empty%
+  \else%
+   \let\exf at sheet@points at given\@undefined%
+   \ifcsname exf at sheetpoints@\sheettag\endcsname%
+    \exf at csdotwo\let\exf at tmp{exf at sheetpoints@\sheettag}%
+    \exf at exptwo\exf at scanpoints\exf at sheet@points\exf at tmp++&%
   \fi\fi%
   \exf at ifis\exf at metadata{sheet}{\exf at writemetadata{sheet}}%
   \exf at config@insertsheetbefore%
@@ -768,7 +867,7 @@
    {\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%
+ {\ifdefined\exf at sheet@points at given%
    \exf at warnmismatch{\exf at sheetname}{\exf at sheetcounter}%
     {\exf at sheet@points at total}{\exf at sheet@points}%
   \else%
@@ -792,12 +891,12 @@
   \clearpage\ifexf at twoside\ifodd\value{page}\else%
   \thispagestyle{empty}\hbox{}\newpage\fi\fi}
 
-\define at key{exf at problem}{points}{\exf at scanpoints\exf at points@given#1++&}
+\define at key{exf at problem}{points}{\exf at scanpoints\exf at problem@points#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][]{%
+\newenvironment{printproblem}[1]{%
   \par\exf at config@styletext\addvspace{\exf at config@skipproblemabove}%
   \refstepcounter{\exf at problemcounter}%
   \exf at config@insertproblembefore%
@@ -811,11 +910,11 @@
   \fi%
   \exf at init@block{\exf at config@skipprobleminfo}%
   \def\problemtag{\csname the\exf at problemcounter\endcsname}%
-  \let\exf at points@given\@undefined%
+  \let\exf at problem@points\@undefined%
   \let\exf at label\@undefined%
   \global\let\exf at sollabel\@undefined%
   \let\exf at problem@points at total\@undefined%
-  \setkeys{exf at problem,exf at probleminfo}{#1}%
+  \setkeys{exf at problem,exf at probleminfo,exf at scanproblem}{#1}%
   \ifexf at autolabelproblem\label{\exf at config@labelproblem{\problemtag}}\fi%
   \ifdefined\exf at label\label{\exf at label}\fi%
   \gdef\exf at problem@solnewsec{}%
@@ -831,12 +930,13 @@
   \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 tmp{exf at problempoints@\problemtag}%
-   \exf at exptwo\exf at scanpoints\exf at problem@points\exf at tmp++&%
+  \ifdefined\exf at problem@points%
+   \let\exf at problem@points at given\exf at empty%
+  \else%
+   \let\exf at problem@points at given\@undefined%
+   \ifcsname exf at problempoints@\problemtag\endcsname%
+    \exf at csdotwo\let\exf at tmp{exf at problempoints@\problemtag}%
+    \exf at exptwo\exf at scanpoints\exf at problem@points\exf at tmp++&%
   \fi\fi%
   \global\let\exf at prevpoints\exf at problem@points%
   \let\exf at problem@points at show\@undefined%
@@ -845,9 +945,9 @@
   \fi%
   \exf at ifis\exf at pointsat{off}{\let\exf at problem@points at show\@undefined}%
   \exf at ifis\exf at pointsat{start}{\exf at outpoints{\exf at append@intro}%
-   {\exf at config@composepointspairstart}{\exf at problem@points at show}}%
+   {\exf at config@composepointspairstartproblem}{\exf at problem@points at show}}%
   \exf at ifis\exf at pointsat{start*}{\exf at outpoints{\exf at prepend@intro}%
-   {\exf at config@composepointspairstart}{\exf at problem@points at show}}%
+   {\exf at config@composepointspairstartproblem}{\exf at problem@points at show}}%
   \exf at config@insertprobleminfo%
   \exf at config@styletextproblem%
   \ifdim\exf at config@skipproblemitem=0pt%
@@ -883,7 +983,7 @@
     {\exf at data@problem at rawtitle}}%
   \@afterindentfalse}%
  {\exf at ifis\exf at pointsat{end}{\showpoints}%
-  \ifdefined\exf at points@given%
+  \ifdefined\exf at problem@points at given%
    \exf at warnmismatch{\exf at problemname}{\exf at problemcounter}%
     {\exf at problem@points at total}{\exf at problem@points}%
   \else%
@@ -915,6 +1015,91 @@
    \exf at showsolutions{\exf at config@composetitlesolutionmulti}{}}%
   \ignorespacesafterend}
 
+\define at boolkey{exf at scanproblem}[exf at scanproblem@]{disable}[true]{}
+
+\newenvironment{exf at problem@direct}[1][]%
+ {\printproblem{#1}}{\endprintproblem\ignorespacesafterend}
+
+\newenvironment{exf at problem@scan}%
+ {\exf at scanblock{\exf at scanproblem}}{\endexf at scanproblem}%
+\newenvironment{exf at scanproblem}[2]{%
+  \exf at scanproblem@disablefalse%
+  \setkeys*{exf at scanproblem}{#1}%
+  \exf at config@insertproblemselect{#1}%
+  \ifexf at scanproblem@disable%
+   \def\exf at verbatim@process{\@gobble}%
+  \else%
+   \ifexf at lineno\exf at addline\exf at probbuf{\exf at linesep}%
+    \exf at addline\exf at probbuf{\exf at lineno}\fi%
+   \exf at addline\exf at probbuf%
+    {\@backslashchar begin{printproblem}{#1}}%
+   \def\exf at verbatim@process{\exf at append@buf\exf at probbuf}%
+  \fi%
+  \exf at verbatim#2}%
+ {\exf at endverbatim%
+  \ifexf at scanproblem@disable\else%
+   \exf at addline\exf at probbuf{\@backslashchar end{printproblem}}%
+   \global\exf at probbuf@cleanfalse%
+  \fi%
+  \ifexf at probfile@open%
+   \exf at write@buf\exf at probfile\exf at probbuf%
+   \exf at clear@probbuf%
+  \fi%
+  \ifexf at problemmanual\else%
+   \exf at source@buf\exf at probbuf%
+   \exf at clear@probbuf%
+  \fi%
+  \ignorespacesafterend}
+
+\newenvironment{\exf at problemname}%
+ {\ifexf at problembuf\let\exf at tmp\exf at problem@scan%
+  \else\let\exf at tmp\exf at problem@direct\fi%
+  \exf at tmp}%
+ {\ifexf at problembuf\let\exf at tmp\endexf at problem@scan%
+  \else\let\exf at tmp\endexf at problem@direct\fi%
+  \exf at tmp}
+
+\newcommand{\exf at problemstitle}{%
+  \protected at edef\exf at problemstitleexp{\exf at config@composetitleproblems}%
+  \ifx\exf at problemstitleexp\exf at empty\else%
+   \exf at section{\exf at config@skipproblemstitle}%
+    {\exf at config@styletitle\exf at config@styletitleproblems%
+     \exf at problemstitleexp}%
+   \exf at addcontentsline{\exf at config@toclevelproblems}%
+    {\exf at config@composetocproblems}%
+  \fi}
+
+\newcommand{\exf at showproblemsin}{%
+  \par\exf at config@styletext\addvspace{\exf at config@skipproblemsabove}%
+  \exf at config@insertproblemsbefore}
+
+\newcommand{\exf at showproblemsout}{%
+  \exf at config@insertproblemsafter%
+  \par\exf at config@styletext\addvspace{\exf at config@skipproblemsbelow}}
+
+\newcommand{\exf at showproblems}{%
+  \ifexf at probbuf@clean\else\begingroup%
+   \exf at showproblemsin%
+   \exf at problemstitle%
+   \exf at source@buf\exf at probbuf%
+   \exf at clear@probbuf%
+   \exf at showproblemsout%
+  \endgroup\fi}
+
+\newcommand{\writeproblems}[1][\jobname]{%
+  \exf at close@probfile\exf at start@probfile{#1}}
+
+\newcommand{\closeproblems}{\exf at close@probfile}
+
+\newcommand{\readproblems}[1][\jobname]{\exf at close@probfile%
+  \begingroup%
+   \exf at config@styletext\exf at config@styletextproblem%
+   \exf at problemstitle%
+   \input{#1\exf at config@extproblems}%
+  \endgroup}
+
+\newcommand{\insertproblems}{\exf at showproblems}
+
 \define at key{exf at subproblem}{points}{\exf at scanpoints\exf at subproblem@points#1++&}
 \define at key{exf at subproblem}{label}{\def\exf at label{#1}}
 
@@ -934,7 +1119,11 @@
    \xdef\exf at prevsubprobhref{\exf at subproblemcounter.%
     \csname theH\exf at subproblemcounter\endcsname}%
   \fi%
+  \let\exf at subproblem@points at show\@undefined%
   \ifdefined\exf at subproblem@points%
+   \let\exf at subproblem@points at show\exf at subproblem@points\fi%
+  \exf at ifis\exf at subpointsat{off}{\let\exf at subproblem@points at show\@undefined}%
+  \ifdefined\exf at subproblem@points%
    \global\let\exf at prevpoints\exf at subproblem@points%
    \exf at exptwo\exf at addtopoints\exf at problem@points at total\exf at subproblem@points%
   \else%
@@ -942,11 +1131,10 @@
     \PackageWarning{exframe}{no points defined for \exf at subproblemname}%
    \fi%
   \fi%
-  \exf at ifis\exf at subpointsat{off}{\let\exf at subproblem@points\@undefined}%
   \exf at ifis\exf at subpointsat{start}{\exf at outpoints{\exf at append@intro}%
-   {\exf at config@composepointspairstart}{\exf at subproblem@points}}%
+   {\exf at config@composepointspairstartsubproblem}{\exf at subproblem@points at show}}%
   \exf at ifis\exf at subpointsat{start*}{\exf at outpoints{\exf at prepend@intro}%
-   {\exf at config@composepointspairstart}{\exf at subproblem@points}}%
+   {\exf at config@composepointspairstartsubproblem}{\exf at subproblem@points at show}}%
   \exf at config@insertsubprobleminfo%
   \ifdim\exf at config@skipsubproblemitem=0pt%
    \exf at prepend@intro{{%
@@ -970,7 +1158,7 @@
   \fi%
   \exf at ifis\exf at subpointsat{margin}{%
    \exf at outpoints{\exf at prepend@def\exf at introitem}%
-   {\exf at makepointsmargin}{\exf at subproblem@points}}%
+   {\exf at makepointsmargin}{\exf at subproblem@points at show}}%
   \exf at open@block{\exf at config@skipsubproblemtitle}%
   \@afterindentfalse}%
  {\exf at ifis\exf at subpointsat{end}{\showpoints}%
@@ -1004,9 +1192,11 @@
    \let\theHequation\theHexf at solutionequation%
   \fi%
   \begingroup%
+  \def\exf at in@solution{}%
   \def\exf at solprob{}%
   \def\exf at solsubprob{}%
   \let\exf at label\@undefined%
+  \let\exf at solution@points\@undefined%
   \let\exf at solution@points at total\@undefined%
   \def\exf at solhref{}%
   \exf at init@block{\exf at config@skipsolutioninfo}%
@@ -1015,6 +1205,14 @@
    {\exf at config@composeitemsolutionlabel{\exf at solprob}{\exf at solsubprob}}%
   \refstepcounter{\exf at solutioncounter}%
   \ifdefined\exf at label\label{\exf at label}\fi%
+  \let\exf at solution@points at show\@undefined%
+  \ifdefined\exf at solution@points%
+   \let\exf at solution@points at show\exf at solution@points\fi%
+  \exf at ifis\exf at solpointsat{off}{\let\exf at solution@points at show\@undefined}%
+  \exf at ifis\exf at solpointsat{start}{\exf at outpoints{\exf at append@intro}%
+   {\exf at config@composepointspairstartsolution}{\exf at solution@points at show}}%
+  \exf at ifis\exf at solpointsat{start*}{\exf at outpoints{\exf at prepend@intro}%
+   {\exf at config@composepointspairstartsolution}{\exf at solution@points at show}}%
   \exf at config@insertsolutioninfo%
   \exf at config@styletext\exf at config@styletextsolution%
   \ifx\exf at solsubprob\exf at empty%
@@ -1058,9 +1256,13 @@
     \else\exf at solution@item\fi%
     \exf at config@composeitemproblemsep}}%
   \fi%
+  \exf at ifis\exf at solpointsat{margin}{%
+   \exf at outpoints{\exf at prepend@def\exf at introitem}%
+   {\exf at makepointsmargin}{\exf at solution@points at show}}%
   \exf at open@block{\exf at config@skipsolutiontitle}%
   \@afterindentfalse}%
- {\exf at warnmismatch{\exf at solutionname}{\exf at solutioncounter}%
+ {\exf at ifis\exf at solpointsat{end}{\showpoints}%
+  \exf at warnmismatch{\exf at solutionname}{\exf at solutioncounter}%
    {\exf at solution@points at total}{\exf at solution@points}%
   \par\exf at close@block%
   \ifexf at style@solutionequation%
@@ -1080,28 +1282,20 @@
   \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 ifis\exf at solutionbelow{problem}{\let\exf at composetitle%
     \exf at config@composetitlesolutionsproblemsingle}%
   \exf at ifis\exf at solutionbelow{problem*}{\let\exf at composetitle%
     \exf at config@composetitlesolutionsproblemsingle}%
+  \def\exf at solutionstoc{\exf at addcontentsline{\exf at config@toclevelsolution}%
+    {\exf at config@composetocsolution{\exf at solprob}{\exf at solprobtitle}}}%
+  \addvspace{\exf at config@skipsolutionsproblemabove}%
   \exf at solutionssection{\exf at config@styletitlesolutionsproblem}%
    {\exf at composetitle{\exf at solprob}{\exf at solprobtitle}}%
-   {\exf at config@skipsolutionsproblem}%
+   {\exf at config@skipsolutionsproblemtitle}%
    {\exf at solutionstoc}{\exf at label}{\exf at solhref}%
   \endgroup}
 
-\newenvironment{\exf at solutionname}%
-  {\exf at ifis\exf at solutionbelow{here*}{%
-    \newcommand{\exf at scanblockplain}[1][]{\exf at scansolution{##1}{}}%
-    \def\exf at scanblock##1{\exf at scanblockplain}}%
-   \exf at scanblock{\exf at scansolution}}{\endexf at scansolution}%
-
-\newenvironment{exf at scansolution}[2]{%
-  \exf at ifis\exf at solutionbelow{here}{\showpoints}%
-  \exf at ifis\exf at solutionbelow{here*}{\showpoints}%
-  \global\exf at bufcleanfalse%
+\newcommand{\exf at process@solnewsec}{%
   \ifdefined\exf 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%
@@ -1108,18 +1302,19 @@
     \ifdefined\exf at prevprobhref,href={\exf at prevprobhref}\fi%
     \ifdefined\exf at sollabel,label={\exf at sollabel}\fi}%
    \exf at ifis\exf at solutionbelow{here}{\let\exf at probarg\@undefined}%
-   \exf at ifis\exf at solutionbelow{here*}{\let\exf at probarg\@undefined}%
    \exf at ifis\exf at solutionbelow{subproblem}{\let\exf at probarg\@undefined}%
    \exf at ifis\exf at solutionbelow{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{}%
+    \ifexf at lineno\exf at addline\exf at solbuf{\exf at linesep}%
+     \exf at addline\exf at solbuf{\exf at lineno}\fi%
+    \exf at addline\exf at solbuf{\@backslashchar solutionssection{\exf at probarg}}%
+    \exf at addline\exf at solbuf{}%
    \fi%
    \global\let\exf at problem@solnewsec\@undefined%
-  \fi%
-  \ifexf at lineno\exf at addbufline{\exf at linesep}\exf at addbufline{\exf at lineno}\fi%
-  \def\exf at subprobarg{%
+  \fi}%
+
+\newcommand{\exf at generate@solprobarg}{%
+  \edef\exf at solprobarg{%
     \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%
@@ -1130,24 +1325,41 @@
      {\expandafter\exf at formatpoints\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 ifis\exf at solutionbelow{here*}{%
-   \def\exf at verbatim{\exf at clearbuf\begingroup%
-    \edef\exf at subprobarg{\exf at subprobarg}%
-    \exf at showsolutionsin{\exf at config@composetitlesolutionsingle}%
-    \exf at exptwo\printsolution{\exf at subprobarg#1}}%
-   \def\exf at endverbatim{\endprintsolution\exf at showsolutionsout\endgroup}}%
+  \global\let\exf at prevpoints\@undefined}%
+
+\newenvironment{exf at solution@direct}[1][]%
+ {\showpoints%
+  \global\let\exf at problem@solnewsec\@undefined%
+  \exf at generate@solprobarg%
+  \exf at showsolutionsin%
+  \let\exf at composetitle\exf at config@composetitlesolutionsingle%
+  \exf at exptwo\printsolution{\exf at solprobarg#1}}%
+ {\endprintsolution%
+  \exf at showsolutionsout%
+  \ignorespacesafterend}%
+
+\newenvironment{exf at solution@scan}%
+ {\exf at scanblock{\exf at scansolution}}{\endexf at scansolution}%
+\newenvironment{exf at scansolution}[2]{%
+  \exf at ifis\exf at solutionbelow{here}{\showpoints}%
+  \exf at process@solnewsec%
+  \exf at generate@solprobarg%
+  \ifexf at lineno\exf at addline\exf at solbuf{\exf at linesep}%
+   \exf at addline\exf at solbuf{\exf at lineno}\fi%
+  \exf at addline\exf at solbuf%
+   {\@backslashchar begin{printsolution}{\exf at solprobarg#1}}%
+  \def\exf at verbatim@process{\exf at append@buf\exf at solbuf}%
   \exf at verbatim#2}%
  {\exf at endverbatim%
-  \exf at addbufline{\@backslashchar end{printsolution}}%
-  \ifexf at infile%
-   \exf at writebuf%
-   \exf at clearbuf%
+  \exf at addline\exf at solbuf{\@backslashchar end{printsolution}}%
+  \global\exf at solbuf@cleanfalse%
+  \ifexf at solfile@open%
+   \exf at write@buf\exf at solfile\exf at solbuf%
+   \exf at clear@solbuf%
   \fi%
-  \ifsolutions\else\exf at clearbuf\fi%
+  \ifsolutions\else\exf at clear@solbuf\fi%
   \exf at ifis\exf at solutionbelow{here}{\exf at showsolutions%
    {\exf at config@composetitlesolutionsingle}{}}%
   \ifdefined\exf at in@subproblem\else%
@@ -1162,6 +1374,14 @@
     \exf at showsolutions{\exf at config@composetitlesolutionmulti}{}}\fi%
   \ignorespacesafterend}
 
+\newenvironment{\exf at solutionname}%
+ {\ifexf at solutionbuf\let\exf at tmp\exf at solution@scan%
+  \else\let\exf at tmp\exf at solution@direct\fi%
+  \exf at tmp}%
+ {\ifexf at solutionbuf\let\exf at tmp\endexf at solution@scan%
+  \else\let\exf at tmp\endexf at solution@direct\fi%
+  \exf at tmp}
+
 \newcommand{\exf at solutionssection}[6]{%
   \protected at edef\exf at solutionstitleexp{#2}%
   \ifx\exf at solutionstitleexp\exf at empty\else%
@@ -1181,36 +1401,36 @@
    {\exf at addcontentsline{\exf at config@toclevelsolutions}%
     {\exf at config@composetocsolutions}}{\@undefined}{\@undefined}}
 
-\newcommand{\exf at showsolutionsin}[1]{%
+\newcommand{\exf at showsolutionsin}{%
   \par\exf at config@styletext\addvspace{\exf at config@skipsolutionsabove}%
   \exf at config@styletextsolution%
-  \exf at config@insertsolutionsbefore%
-  \let\exf at composetitle#1}
+  \exf at config@insertsolutionsbefore}
 
 \newcommand{\exf at showsolutionsout}{%
-  \removelastskip%
   \exf at config@insertsolutionsafter%
-  \par\exf at config@styletext\addvspace{\exf at config@skipsolutionbelow}}
+  \par\exf at config@styletext\addvspace{\exf at config@skipsolutionsbelow}}
 
 \newcommand{\exf at showsolutions}[2]{%
-  \ifexf at bufclean\else\begingroup%
-   \exf at showsolutionsin{#1}%
+  \ifexf at solbuf@clean\else\begingroup%
+   \exf at showsolutionsin%
+   \let\exf at composetitle#1%
    #2%
-   \exf at sourcebuf%
-   \exf at clearbuf%
+   \exf at source@buf\exf at solbuf%
+   \exf at clear@solbuf%
    \exf at showsolutionsout%
   \endgroup\fi}
 
-\newcommand{\writesolutions}[1][\jobname]{\exf at closefile\exf at startfile{#1}}
+\newcommand{\writesolutions}[1][\jobname]{%
+  \exf at close@solfile\exf at start@solfile{#1}}
 
-\newcommand{\closesolutions}{\exf at closefile}
+\newcommand{\closesolutions}{\exf at close@solfile}
 
-\newcommand{\readsolutions}[1][\jobname]{\exf at closefile%
+\newcommand{\readsolutions}[1][\jobname]{\exf at close@solfile%
   \ifsolutions\begingroup%
    \exf at config@styletext\exf at config@styletextsolution%
-   \let\exf at config@composetitlesolution\exf at config@composetitlesolutionmulti%
+   \let\exf at composetitle\exf at config@composetitlesolutionmulti%
    \exf at solutionstitle%
-   \input{#1.sol}%
+   \input{#1\exf at config@extsolutions}%
   \endgroup\fi}
 
 \newcommand{\insertsolutions}{\exf at showsolutions%



More information about the tex-live-commits mailing list