texlive[53911] Master/texmf-dist: exframe (25feb20)

commits+karl at tug.org commits+karl at tug.org
Tue Feb 25 23:03:03 CET 2020


Revision: 53911
          http://tug.org/svn/texlive?view=revision&revision=53911
Author:   karl
Date:     2020-02-25 23:03:03 +0100 (Tue, 25 Feb 2020)
Log Message:
-----------
exframe (25feb20)

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/exfser01.tex
    trunk/Master/texmf-dist/doc/latex/exframe/exfser02.tex
    trunk/Master/texmf-dist/doc/latex/exframe/exfseraa.tex
    trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex
    trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.mak
    trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.sh
    trunk/Master/texmf-dist/doc/latex/exframe/exfserpe.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	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/README.txt	2020-02-25 22:03:03 UTC (rev 53911)
@@ -1,4 +1,4 @@
-exframe v3.31
+exframe v3.4
 Copyright 2011-2020 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	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfsamp.tex	2020-02-25 22:03:03 UTC (rev 53911)
@@ -17,7 +17,7 @@
 %% version 2005/12/01 or later.
 %% 
 \NeedsTeXFormat{LaTeX2e}[1996/12/01]
-\ProvidesFile{exfsamp.tex}[2020/01/11 v3.31 standalone sample for exframe]
+\ProvidesFile{exfsamp.tex}[2020/02/24 v3.4 standalone sample for exframe]
 \documentclass[12pt]{article}
 
 \usepackage{geometry}
@@ -29,11 +29,19 @@
 
 \usepackage{amsmath}
 \usepackage{hyperref}
+
+\PassOptionsToPackage{loadlang=en|de}{metastr}
+\PassOptionsToPackage{course=true}{metastr}
+%%\usepackage{metastr}
+%%\metasetlang{de}
+
 \usepackage[extstyle]{exframe}
 
-\exercisesetup{solutions=true}
-%%\exercisesetup{solutions=false}
+%%\exercisesetup{solutions=true}
+\exercisesetup{solutions=false}
 
+\exercisesetup{autolabelproblem=true}
+
 \exercisestyle{plainheader}
 \exerciseconfig{composeheaderbelowright}{\getsheetdata{points}}%
 
@@ -46,13 +54,20 @@
    \hspace{-\getexerciseconfig{skipsubprobleminfo}}*}}%
   {}{}{\getsubproblempoints{}}}
 
+\ifdefined\metaset
+\metasetterm[en]{sheet}{Exercise Sheet}
+\metasetterm[en]{sheets}{Exercise Sheets}
+\metasetterm[de]{sheet}{\"Ubungsblatt}
+\metasetterm[de]{sheets}{\"Ubungsbl\"atter}
+\else
 \exerciseconfig{termsheet}{\"Ubungsblatt}
 \exerciseconfig{termsheets}{\"Ubungsbl\"atter}
+\fi
 
 \exercisestyle{problempointsat=margin}
 \reversemarginpar
 \exerciseconfig{composepointsmargin}[1]{#1p.}
-\exerciseconfig{composepointspairmargin}[2]{
+\exerciseconfig{composepointspairmargin}[2]{%
   \ifdim#2pt=0pt#1p.%
   \else\ifdim#1pt=0pt+#2p.%
   \else#1+#2p.%
@@ -66,27 +81,65 @@
 \exercisestyle{solutionbelow=problem}
 \exercisestyle{solutionsep}
 
+\exercisesetup{pdfdata=sheet}
+
+\ifdefined\metaset
+\metaset[sep]{subtitle}{, }
+\metaset{subtitle}{\ifsolutions\metatranslate[#1]{solutions} \fi%
+  \metaif[use]{sheettitle}
+   {\metapick[#1]{sheettitle}}
+   {\metapick[#1]{material}}}
+\metaset{author}{\exerciseifempty{\getsheetdata{author}}%
+  {\metapick[#1]{instructor}}{\metapick[#1]{sheetauthor}},
+  \metapick[#1]{institution}}
+\else
 \exerciseconfig{composemetasheet}[2]{\getexercisedata{course},
+  \ifsolutions\getexerciseconfig{termsolutions} \fi%
   \exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
-
-\exercisesetup{pdfdata=sheet}
 \exercisedata{title=%
-  {\getexercisedata{course}, \getexercisedata{material}}}
+  {\getexercisedata{course},
+  \ifsolutions\getexercisedata{solutions} \fi%
+  \getexercisedata{material}}}
 \exercisedata{author=%
   {\getexercisedata{instructor}, \getexercisedata{institution}}}
+\fi
 
+\ifdefined\metaset
+\metaset{institution}{Katharinen-Volksschule}
+\metaset[de]{course}{Mathematik}
+\metaset[en]{course}{Mathematics}
+\metaset{instructor}{J.\ G.\ B\"uttner}
+\metaset{period}{ca.\ 1786}
+\metaset[de]{material}{\"Ubungsaufgaben}
+\metaset[en]{material}{Exercise Problems}
+\else
 \exercisedata{institution={Katharinen-Volksschule}}
 \exercisedata{course={Mathematik}}
 \exercisedata{instructor={J.\ G.\ B\"uttner}}
 \exercisedata{period={ca.\ 1786}}
 \exercisedata{material={\"Ubungsaufgaben}}
+\fi
 
 \begin{document}
 
-\begin{sheet}[number=5]
+\begin{sheet}[number=5,label={sheet5}]
 
 \begin{problem}[title={Sums},points=99+4]
 
+\exerciseloopstr{\getsubproblemlist{}}{c}%
+\hfill\begin{tabular}{c|\exerciseloopret|c}
+\exerciseloop{\getsubproblemlist{}}
+ {&\ref{\getexerciseconfig{labelsubproblem}{#1}}}
+&\ref{prob:\problemtag}\\\hline
+\getexerciseconfig{termpoints}
+\exerciseloop{\getsubproblemlist{}}{&\extractpoints{\getsubproblempoints{#1}}}
+&\extractpoints{\getproblempoints{}}
+\\
+extra
+\exerciseloop{\getsubproblemlist{}}{&\extractpoints*{\getsubproblempoints{#1}}}
+&\extractpoints*{\getproblempoints{}}
+\end{tabular}
+
 This problem deals with sums and series.
 
 \begin{subproblem}[points=2,difficulty=simple,label={\problemtag-simplesum}]
@@ -215,6 +268,44 @@
 \marginpar{\footnotesize\raggedright does not fit here.\par}
 \end{solution}
 
+\ifsolutions\else
+\textbf{Grading:}\par
+\exerciseloopstr{\getproblemlist{}}{|c}
+\begin{tabular}{|c|\exerciseloopret||c|}\hline
+\getexerciseconfig{termsheet} \ref{sheet5}
+\exerciseloop{\getproblemlist{*}}
+ {&\ref{\getexerciseconfig{labelproblem}{#1}}}
+&total
+\\\hline
+value
+\exerciseloop{\getproblemlist{*}}
+ {&\extractpoints{\getproblempoints{#1}}}%
+&\extractpoints{\getsheetpoints{}}
+\\\hline
+\exerciseloop{\getproblemlist{*}}{&}
+&\\\hline
+\end{tabular}\qquad
+\exerciseloop{\getproblemlist{*}}{
+ \exerciseloopstr{\getsubproblemlist{#1}}{|c}
+ \ifnum\value{exerciseloop}>0\relax
+  \begin{tabular}{|c|\exerciseloopret||c|}\hline
+  \getexerciseconfig{termproblem} \ref{\getexerciseconfig{labelproblem}{#1}}
+  \exerciseloop{\getsubproblemlist{#1}}
+   {&\ref{\getexerciseconfig{labelsubproblem}{##1}}}
+  &total
+  \\\hline
+  value
+  \exerciseloop{\getsubproblemlist{#1}}
+   {&\extractpoints{\getsubproblempoints{##1}}}%
+  &\extractpoints{\getproblempoints{#1}}
+  \\\hline
+  \exerciseloop{\getsubproblemlist{#1}}{&}
+  &\\\hline
+  \end{tabular}\quad
+ \fi
+}
+\fi
+
 \end{sheet}
 
 \end{document}

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfser01.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfser01.tex	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfser01.tex	2020-02-25 22:03:03 UTC (rev 53911)
@@ -28,10 +28,19 @@
 \begin{mpostfig}[label={\problemtag-fig}]
 interim xu:=1.5cm;
 paths[1]:=fullcircle scaled 1xu;
-fill paths[1] withgreyscale 0.7;
-draw paths[1] withpen pencircle scaled 1pt;
+fillshape(paths[1], 0.7white) pensize(1pt);
 label(btex \figure etex, center(paths[1]));
 \end{mpostfig}
+\begin{onlysolutions}
+\begin{mpostfig}[label={\problemtag-solfig}]
+interim xu:=1.5cm;
+paths[1]:=fullcircle scaled 1xu;
+paths[2]:=((subpath (-2,2) of paths[1])--cycle) shifted (+0.5xu,0);
+paths[3]:=((subpath (2,6) of paths[1])--cycle) shifted (-0.5xu,0);
+fillshape(paths[2], 0.7white) pensize(1pt);
+fillshape(paths[3], 0.7white) pensize(1pt);
+\end{mpostfig}
+\end{onlysolutions}
 \fi
 
 \lorem
@@ -46,6 +55,10 @@
 
 \begin{solution}
 \lorem
+\begin{center}
+\ifdefined\mpostuse\mpostuse{\problemtag-solfig}\else figure\fi
+\end{center}
+\lorem
 \end{solution}
 
 \begin{subproblem}

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfser02.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfser02.tex	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfser02.tex	2020-02-25 22:03:03 UTC (rev 53911)
@@ -26,10 +26,19 @@
 \begin{mpostfig}[label={\problemtag-fig}]
 interim xu:=1.5cm;
 paths[1]:=fullcircle scaled 1xu;
-fill paths[1] withgreyscale 0.7;
-draw paths[1] withpen pencircle scaled 1pt;
+fillshape(paths[1], 0.7white) pensize(1pt);
 label(btex \figure etex, center(paths[1]));
 \end{mpostfig}
+\begin{onlysolutions}
+\begin{mpostfig}[label={\problemtag-solfig}]
+interim xu:=1.5cm;
+paths[1]:=fullcircle scaled 1xu;
+paths[2]:=((subpath (-2,2) of paths[1])--cycle) shifted (+0.5xu,0);
+paths[3]:=((subpath (2,6) of paths[1])--cycle) shifted (-0.5xu,0);
+fillshape(paths[2], 0.7white) pensize(1pt);
+fillshape(paths[3], 0.7white) pensize(1pt);
+\end{mpostfig}
+\end{onlysolutions}
 \fi
 
 \lorem
@@ -44,6 +53,10 @@
 
 \begin{solution}
 \lorem
+\begin{center}
+\ifdefined\mpostuse\mpostuse{\problemtag-solfig}\else figure\fi
+\end{center}
+\lorem
 \end{solution}
 
 \begin{subproblem}

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfseraa.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfseraa.tex	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfseraa.tex	2020-02-25 22:03:03 UTC (rev 53911)
@@ -26,10 +26,19 @@
 \begin{mpostfig}[label={\problemtag-fig}]
 interim xu:=1.5cm;
 paths[1]:=fullcircle scaled 1xu;
-fill paths[1] withgreyscale 0.7;
-draw paths[1] withpen pencircle scaled 1pt;
+fillshape(paths[1], 0.7white) pensize(1pt);
 label(btex \figure etex, center(paths[1]));
 \end{mpostfig}
+\begin{onlysolutions}
+\begin{mpostfig}[label={\problemtag-solfig}]
+interim xu:=1.5cm;
+paths[1]:=fullcircle scaled 1xu;
+paths[2]:=((subpath (-2,2) of paths[1])--cycle) shifted (+0.5xu,0);
+paths[3]:=((subpath (2,6) of paths[1])--cycle) shifted (-0.5xu,0);
+fillshape(paths[2], 0.7white) pensize(1pt);
+fillshape(paths[3], 0.7white) pensize(1pt);
+\end{mpostfig}
+\end{onlysolutions}
 \fi
 
 \lorem
@@ -44,6 +53,10 @@
 
 \begin{solution}
 \lorem
+\begin{center}
+\ifdefined\mpostuse\mpostuse{\problemtag-solfig}\else figure\fi
+\end{center}
+\lorem
 \end{solution}
 
 \begin{subproblem}

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfserm.tex	2020-02-25 22:03:03 UTC (rev 53911)
@@ -17,16 +17,17 @@
 %% version 2005/12/01 or later.
 %% 
 \NeedsTeXFormat{LaTeX2e}[1996/12/01]
-\ProvidesFile{exfserm.tex}[2020/01/11 v3.31 multipart sample for exframe]
+\ProvidesFile{exfserm.tex}[2020/02/24 v3.4 multipart sample for exframe]
 \input{childdoc.def}
 \childdocmain{exfserm}
 
-\providecommand{\draftver}{y}
 \ifchilddoc
 \providecommand{\printsol}{y}
 \else
 \providecommand{\printsol}{n}
 \fi
+\providecommand{\draftver}{y}
+\newif\ifdraft\if\draftver y\drafttrue\else\draftfalse\fi
 
 \documentclass[12pt]{article}
 
@@ -35,8 +36,15 @@
 \PassOptionsToPackage{bookmarks=\ifchilddoc false\else true\fi}{hyperref}
 \PassOptionsToPackage{bookmarksopen=true}{hyperref}
 \RequirePackage{hyperref}
-\IfFileExists{hyperxmp.sty}{\RequirePackage{hyperxmp}}{}
 
+\ifdraft
+\PassOptionsToPackage{draft}{metastr}
+\fi
+\IfFileExists{hyperxmp.sty}{}{\PassOptionsToPackage{hyperxmp=false}{metastr}}
+\RequirePackage[course]{metastr}
+\metaset[aux]{writepdf}{}
+\metaset[rights]{writepdf}{}
+
 \RequirePackage[extdata,extstyle]{exframe}
 
 \if\printsol n
@@ -45,7 +53,10 @@
 \else
 \exercisesetup{solutions=true}
 \exercisesetup{twoside=false}
+\ifdraft
+\exercisesetup{solutionbuf=false}
 \fi
+\fi
 
 %%\if\printsol n\else\showprobleminfo{author,source,recycle}\fi
 
@@ -57,6 +68,13 @@
 \exercisestyle{solutionbelow={problem}}
 \ifchilddoc\ifchilddocmanual\else\exercisesetup{pdfdata=sheet}\fi\fi
 
+\metasetlang{en-GB}
+
+\metasetterm[en]{sheet}{sheet}
+\metasetterm[en]{sheets}{sample sheets}
+\metasetterm[en]{solution}{Solution}
+\metasetterm[en]{solutions}{solutions}
+
 \RequirePackage[a4paper,margin=2.5cm]{geometry}
 \pagestyle{plain}
 \setlength\parindent{0pt}
@@ -86,9 +104,8 @@
 \ifdefined\mpostsetup
 
 \mpostsetup{checksum}
-\if\draftver y\mpostsetup{now,nowall}\fi
+\ifchilddoc\ifdraft\mpostsetup{now,nowall}\fi\fi
 \ifchilddocmanual\else\mpostsetup{numberwithin={sheet}}\fi
-\ifsolutions\else\mpostsetup{warnunused=false}\fi
 
 \mpostsetup{globaldef=true}
 \begin{mposttex}
@@ -98,74 +115,53 @@
 path paths[];
 newinternal numeric xu;
 xu:=1cm;
+def pensize(expr s)=withpen pencircle scaled s enddef;
+def fillshape(expr p,c)=
+  fill p withcolor c;
+  draw p
+enddef;
 \end{mpostdef}
 \mpostsetup{globaldef=false}
 
 \fi
 
-\exercisedata{course={exframe package samples}}
-\exercisedata{instructor={N.\ Beisert}}
-\exercisedata{institution={exframe academy}}
-\exercisedata{period={spring 2019}}
-\exercisedata{date={2019}}
+\metaset{course}{exframe package samples}
+\metaset{instructor}{N.\ Beisert}
+\metaset{author}{Niklas Beisert, \metapick[#1]{institution}}
+\metaset{institution}{exframe academy}
+\metaset{period}{spring 2019}
+\metaset{copyrightdate}{2019--2020}
 
-\exercisedata{material={\ifsolutions\getexerciseconfig{termsolutions}%
-  \else\getexerciseconfig{termsheets}\fi}}
+\metaset{material}{\metatranslate[#1]{sheets}}
 \exerciseconfig{composetitlesheet}[2]{\exerciseifempty{#2}%
-  {\ifsolutions\getexerciseconfig{termsolutions}\else%
-   \getexerciseconfig{termsheet}\fi\ #1}%
-  {\ifsolutions\getexerciseconfig{termsolutions}\fi\ #2}}
-\exerciseconfig{composemetasheet}[2]{\if\draftver yDRAFT: \fi%
-  \getexercisedata{course},
-  \getexerciseconfig{composetitlesheet}{#1}{#2}}
+  {\ifsolutions\metaterm{solutions}\else%
+   \metaterm{sheet}\fi\ #1}%
+  {\ifsolutions\metaterm{solutions} \fi #2}}
 
-\exercisedata{title={\if\draftver yDRAFT: \fi%
-  \getexercisedata{course}, \getexercisedata{material}}}
-\exercisedata{author={Niklas Beisert, \getexercisedata{institution}}}
-\exercisedata{subject={lecture series at \getexercisedata{institution},
-  \getexercisedata{period}}}
+\ifchilddoc
+\metaset{partof}{\metatranslate[#1]{sheets} \metapick[#1]{course}}
+\fi
 
-\exerciseconfig{termsheet}{sheet}
-\exerciseconfig{termsheets}{sample sheets}
-\exerciseconfig{termsolution}{Solution}
-\exerciseconfig{termsolutions}{solutions}
+\metaset[sep]{draft}{ -- }
+\metaset[sep]{subtitle}{, }
+\metaset{subtitle}{\ifsolutions\metatranslate[#1]{solutions} \fi%
+  \metaif[use]{sheettitle}{\metapick[#1]{sheettitle}}{\metapick[#1]{material}}}
+\metaset{subject}{Lecture Series,
+  \metapick[#1]{institution}, \metapick[#1]{period}}
 
-\def\copyrightmessage
-  {This document as well as its parts is protected by copyright.}
-\def\licensemessage
-  {Reproduction of any part of this work in any form
-  without prior written consent of \getexercisedata{institution}
-  is not permissible.}
+\metaset{copyrightowner}{\metapick[#1]{author}}
+\ifchilddoc
+\metacopyright{doc}
+\else
+\metacopyright{doc-parts}
+\fi
+\metaset{licenseprovider}{of \metapick[#1]{institution}}
+\metalicense{consent}
 
-\ifsolutions\else\if\draftver y\else
-\def\licensecctype{by-sa}
-\def\licenseccname{Attribution-ShareAlike \licenseccver{} International}
+\ifsolutions\else\ifdraft\else
+\metalicensecc{by-sa}
 \fi\fi
 
-\ifdefined\licensecctype
-\ifdefined\licenseccver\else\def\licenseccver{4.0}\fi
-\def\licenseurl
-  {https://creativecommons.org/licenses/\licensecctype/\licenseccver}
-\def\licensemessage{\texorpdfstring
-  {This work is licensed under the Creative Commons ``\licenseccname'' License
-  (CC \MakeUppercase{\licensecctype} \licenseccver).\par
-  \IfFileExists{doclicense.sty}{
-   \begin{center}\includegraphics{doclicense-CC-\licensecctype}\end{center}}{}
-  To view a copy of this license, visit: \url{\licenseurl}}
-  {This work is licensed under the Creative Commons \licenseccname{} License.}}
-\fi
-
-\ifdefined\xmptilde
-\hypersetup{pdfcopyright={Copyright \getexercisedata{date}
-  \getexercisedata{author}. \copyrightmessage{} \licensemessage}}
-\ifdefined\sourceurl\hypersetup{pdflicenseurl={\sourceurl}}\else
-\ifdefined\licenseurl\hypersetup{pdflicenseurl={\licenseurl}}\fi\fi
-\hypersetup{keeppdfinfo=true}
-\hypersetup{pdfsource={}}
-\XMPLangAlt{en}{pdfcopyright={Copyright \getexercisedata{date}
-  \getexercisedata{author}. \copyrightmessage{} \licensemessage}}
-\fi
-
 \begin{document}
 
 \def\tmp{}
@@ -178,33 +174,20 @@
 \begingroup\ifchilddoc\else
 \renewcommand{\thepage}{\arabic{page}}
 
-\pdfbookmark[1]{Title Page}{title}
+\pdfbookmark[1]{\metaterm{title}}{title}
 \thispagestyle{empty}
 \vspace*{\fill}
 \begin{center}
-\begingroup\bfseries\LARGE\getexercisedata{course}\par\endgroup
-\vspace{0.5cm}
-\begingroup\large\getexercisedata{material}\par\endgroup
-\vspace{0.5cm}
-\begingroup\large\getexercisedata{institution},
-  \getexercisedata{period}\par\endgroup
-\vspace{2cm}
-\begingroup\scshape\Large\getexercisedata{instructor}\par\endgroup
+\metapick[course]{titletext}
 \end{center}
 \vspace*{\fill}\vspace*{\fill}
 \newpage
 
-\phantomsection\pdfbookmark[1]{Copyright}{copyright}
+\phantomsection\pdfbookmark[1]{\metaterm{copyright}}{copyright}
 \thispagestyle{empty}
 \vspace*{\fill}\vspace*{\fill}
-\begin{center}
-\begin{minipage}{11cm}\raggedright
-{\copyright} \getexercisedata{date} \getexercisedata{author}
-\par\medskip
-\copyrightmessage{}
-\licensemessage
-\ifdefined\sourcemessage\par\medskip\sourcemessage\fi
-\ifdefined\attributionmessage\par\medskip\attributionmessage\fi
+\begin{center}\begin{minipage}{11cm}\raggedright
+\metapick[print]{rightstext}
 \end{minipage}\end{center}
 \vspace*{\fill}\vspace*{\fill}\vspace*{\fill}
 \newpage
@@ -211,7 +194,7 @@
 
 \makeatletter\renewcommand\@pnumwidth{2.4em}\makeatother
 \setcounter{tocdepth}{2}
-\phantomsection\pdfbookmark[1]{Contents}{contents}
+\phantomsection\pdfbookmark[1]{\metaterm{contents}}{contents}
 {\parskip0pt\tableofcontents}
 \exercisecleardoublepage\setcounter{page}{1}
 

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.mak
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.mak	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.mak	2020-02-25 22:03:03 UTC (rev 53911)
@@ -11,7 +11,8 @@
 TRGMAINFILES = $(foreach trg,$(TRGLIST),$(trg).pdf)
 TRGSECFILES = $(foreach trg,$(TRGLIST),$(trg).pdf $(SECNUM:%=$(trg)%.pdf))
 GENFILES = $(foreach trg,$(TRGLIST),$(trg).tex $(SECNUM:%=$(trg)%.tex))
-BAKFILES = $(PREREQS) $(SRCSECFILES) $(GENFILES) $(MAKEFILE) $(SCRIPT) $(SRCPRB)*
+BAKFILES = $(PREREQS) $(SRCSECFILES) $(GENFILES)\
+           $(MAKEFILE) $(SCRIPT) $(SRCPRB)*
 
 default: sheets ;
 main: $(TRGMAINFILES) ;
@@ -35,7 +36,8 @@
 	rm -f $(foreach ext,.aux .log,$(SECNUM:%=$(SRCSEC)%$(ext)))
 	rm -f $(foreach trg,$(TRGLIST),$(SECNUM:%=$(trg)%.log) $(trg).log)
 	rm -f $(foreach ext,.aux .log .out .toc,$(SRCMAIN)$(ext))
-	rm -f $(foreach ext,.mp .mpx -*.mps -tmp.log -tmp.mp -tmp.mpx,$(SRCMAIN)$(ext))
+	rm -f $(foreach ext,.mp .mpx -*.mps,$(SRCMAIN)$(ext))
+	rm -f $(foreach ext,-tmp.log -tmp.mp -tmp.mpx,$(SRCMAIN)$(ext))
 	rm -f mpxerr.tex mpxerr.log mpxerr.dvi texput.log
 	rm -f $(patsubst %,$(SRCPRB)*%,.aux .log .mp .mpx -*.mps)
 	rm -f $(patsubst %,$(SRCPRB)*%,-tmp.log -tmp.mp -tmp.mpx)

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.sh
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.sh	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfsermk.sh	2020-02-25 22:03:03 UTC (rev 53911)
@@ -62,7 +62,7 @@
     fwd="\\childdocforward[$srcmain]{$srcsec$num}"
   fi
   body="\\def\\jobname{$job}$optdef\\input{childdoc.def}$fwd"
-  for pass in first main
+  for pass in first main extra
   do
     par="";
     if [[ "$pass" == "first" ]]; then par="-draftmode"; fi
@@ -71,7 +71,8 @@
     pdflatex -shell-escape -interaction=batchmode $par \
       -jobname "$trg" "$body" | grep -vE "$drop"
     if [[ "$pass" != "main" ]]; then continue; fi
-    if ! (grep -E -q "may have changed|rerunfilecheck Warning" "$trg.log"); then break; fi
+    if ! (grep -E -q "may have changed|rerunfilecheck Warning" "$trg.log")
+      then break; fi
   done
   grep -E "^! |Warning|Error|Undefined|Overfull|Underfull" "$trg.log"
 }

Modified: trunk/Master/texmf-dist/doc/latex/exframe/exfserpe.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/exframe/exfserpe.tex	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/doc/latex/exframe/exfserpe.tex	2020-02-25 22:03:03 UTC (rev 53911)
@@ -25,10 +25,19 @@
 \begin{mpostfig}[label={\problemtag-fig}]
 interim xu:=1.5cm;
 paths[1]:=fullcircle scaled 1xu;
-fill paths[1] withgreyscale 0.7;
-draw paths[1] withpen pencircle scaled 1pt;
+fillshape(paths[1], 0.7white) pensize(1pt);
 label(btex \figure etex, center(paths[1]));
 \end{mpostfig}
+\begin{onlysolutions}
+\begin{mpostfig}[label={\problemtag-solfig}]
+interim xu:=1.5cm;
+paths[1]:=fullcircle scaled 1xu;
+paths[2]:=((subpath (-2,2) of paths[1])--cycle) shifted (+0.5xu,0);
+paths[3]:=((subpath (2,6) of paths[1])--cycle) shifted (-0.5xu,0);
+fillshape(paths[2], 0.7white) pensize(1pt);
+fillshape(paths[3], 0.7white) pensize(1pt);
+\end{mpostfig}
+\end{onlysolutions}
 \fi
 
 \lorem
@@ -43,6 +52,10 @@
 
 \begin{solution}
 \lorem
+\begin{center}
+\ifdefined\mpostuse\mpostuse{\problemtag-solfig}\else figure\fi
+\end{center}
+\lorem
 \end{solution}
 
 \begin{subproblem}

Modified: trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/source/latex/exframe/exframe.dtx	2020-02-25 22:03:03 UTC (rev 53911)
@@ -20,11 +20,11 @@
 % exfserpe.tex, exfserpf.tex, exfsermk.sh, exfsermk.mak.
 %
 %<package|samplesingle|samplemultimain>\NeedsTeXFormat{LaTeX2e}[1996/12/01]
-%<package>\ProvidesPackage{exframe}[2020/01/11 v3.31 Framework for Exercise Problems]
-%<samplesingle>\ProvidesFile{exfsamp.tex}[2020/01/11 v3.31 standalone sample for exframe]
-%<samplemultimain>\ProvidesFile{exfserm.tex}[2020/01/11 v3.31 multipart sample for exframe]
+%<package>\ProvidesPackage{exframe}[2020/02/24 v3.4 Framework for Exercise Problems]
+%<samplesingle>\ProvidesFile{exfsamp.tex}[2020/02/24 v3.4 standalone sample for exframe]
+%<samplemultimain>\ProvidesFile{exfserm.tex}[2020/02/24 v3.4 multipart sample for exframe]
 %<*driver>
-\def\thedate#1{2020/01/11}\def\theversion#1{v3.31}
+\def\thedate#1{2020/02/24}\def\theversion#1{v3.4}
 \ProvidesFile{exframe.dtx}[\thedate{} \theversion{} exframe reference manual file]
 \PassOptionsToClass{10pt,a4paper}{article}
 \documentclass{ltxdoc}
@@ -918,9 +918,9 @@
 %
 \begin{center}
 \begin{tabular}{l}
-|\getsheetpoints{|\textit{tag}|}|\\
-|\getproblempoints{|\textit{tag}|}|\\
-|\getsubproblempoints{}|\\
+|\getsheetpoints{|[\textit{tag}]|}|\\
+|\getproblempoints{|[\textit{tag}]|}|\\
+|\getsubproblempoints{|[\textit{tag}]|}|\\
 |\getsolutionpoints{}|
 \end{tabular}
 \end{center}
@@ -1025,8 +1025,10 @@
 \DescribeMacro{tag}
 \DescribeMacro{\sheettag}
 \DescribeMacro{\problemtag}
+\DescribeMacro{\subproblemtag}
 The package provides an additional mechanism to tag sheets and problems.
-Each |sheet| and each |problem| can be assigned a unique tag \textit{tag} by
+Each |sheet|, |problem| and |subproblem|
+can be assigned a unique tag \textit{tag} by
 the environment option:
 %
 \begin{center}
@@ -1035,9 +1037,10 @@
 %
 This tag is used for reading point totals
 as described in \secref{sec:points}.
-Furthermore, the macro |\sheettag| or |\problemtag|
+Furthermore, the macro |\sheettag|, |\problemtag| or |\subproblemtag|
 is set to the tag \textit{tag} within the current environment.
-If no tag is specified it matches the number of the sheet or problem;
+If no tag is specified it defaults to the number
+of the current sheet or (sub)problem;
 note that this number can change by reordering sheets and problems
 and therefore it should not be used to identify the entity from
 other parts of the document.
@@ -1069,6 +1072,53 @@
 \end{center}
 %
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getsheetlist}
+\DescribeMacro{\getproblemlist}
+\DescribeMacro{\getsubproblemlist}
+Tags can also be used to process a list of sheets, problems and subproblems:
+%
+\begin{center}
+\begin{tabular}{l}
+|\getsheetlist{}|\\
+|\getproblemlist{|[\textit{sheet-tag}]\textbar|*}|\\
+|\getsubproblemlist{|[\textit{problem-tag}]|}|\\
+\end{tabular}
+\end{center}
+%
+These commands return a list of sheets, problems and subproblems tags,
+where each item is encapsulated in braces.
+The commands |\get|[|sub|]|problemlist| return the (sub)problems
+within the specified sheet or problem. If no argument is given,
+the current sheet or problem is assumed.
+|\getproblemlist*| returns the list of all problems.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exerciseloop}
+\DescribeMacro{\exerciseloopstr}
+\DescribeMacro{\exerciseloopret}
+\DescribeMacro{exerciseloop}
+The package defines two commands to walk through such a list:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseloop{|\textit{items}|}{|\textit{cmd}|}|\\
+|\exerciseloopstr[|\textit{ret}|]{|\textit{items}|}{|\textit{str}|}|
+\end{tabular}
+\end{center}
+%
+Here, \textit{items} is a list of items in braces,
+and |\exerciseloop| evaluates \textit{cmd}
+for each item of the list where `|#1|' is replaced by the item.
+The command |\exerciseloopstr| concatenates
+the evaluations of \textit{str}
+and returns the resulting string in the macro \textit{ret}
+(which defaults to |\exerciseloopret|).
+Both commands maintain a counter of items |exerciseloop|
+which can be accessed within \textit{cmd}/\textit{str} or
+after |\exerciseloop|[|str|] to obtain the total number of items
+in the list.
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \subsection{Layout}
 \label{sec:layout}
@@ -1226,7 +1276,9 @@
 |\if&#1&#2\else#3\fi| and |\if&#1&\else#2\fi|
 which work assuming that \textit{expr} is not too exotic
 (e.g.\ it should not start with the character `|&|'
-and other special \TeX{} characters or macros are potentially dangerous).
+and other special \TeX{} characters or macros are potentially dangerous;
+also using this within tables can be troublesome;
+the character `|&|' can be reconfigured by the package option |emptytestchar|).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \subsection{Exercise Styles}
@@ -1410,6 +1462,12 @@
 (no value implies |true|, initially set to |false|) --
 define some more advanced styles.
 
+\item |metastr|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+load \textsf{metastr} package and use to handle PDF metadata
+and basic internationalisation,
+see \secref{sec:imp-metastr} for details.
+
 \item |problemenv=|\textit{name} --
 redefine environment name |problem|.
 This and the following alike options may be useful in
@@ -1507,6 +1565,12 @@
 enable/disable buffering for |problem| environments
 in order to control their display.
 
+\item |emptytestchar=|\textit{char}
+(initially set to `|&|') --
+character to use for testing whether an argument |#1|
+is empty via |\if&#1&...\fi|;
+if `|&|' causes trouble within tables, could try `|@|' instead.
+
 \end{itemize}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1612,6 +1676,12 @@
 to indicate the \LaTeX{} source file in the generated metapost file.
 Compatibility with the \textsf{currfile} package
 has been tested with v0.7c (2015/04/23).
+\item
+This package can use the package
+\href{http://ctan.org/pkg/metastr}{\textsf{metastr}}
+to write PDF metadata and to handle basic translations.
+Compatibility with the \textsf{metastr} package
+has been tested with v1.0 (2020/02/06).
 \end{itemize}
 
 There are several other \LaTeX{} packages
@@ -1690,8 +1760,8 @@
 but (presently) misses out on some more advanced features,
 see \secref{sec:suggestions}.
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \iffalse
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \subsection{Suggested Customisations}
 \label{sec:customisations}
 
@@ -1755,9 +1825,9 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \subsection{Revision History}
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \iffalse
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\paragraph{v3.3+:} 2020/01/12
+\paragraph{v3.4+:} 2020/02/25
 
 \begin{itemize}
 \item
@@ -1768,6 +1838,21 @@
 \fi
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.4:} 2020/02/24
+
+\begin{itemize}
+\item
+lists of sheets, problems and subproblems;
+list iterators
+\item
+tags for subproblems, tag customisation
+\item
+interaction with package \textsf{metastr}
+\item
+minor fixes
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \paragraph{v3.31:} 2020/01/11
 
 \begin{itemize}
@@ -1970,11 +2055,23 @@
 \parskip0.5ex
 %    \end{macrocode}
 
-% Include \textsf{amsmath}, \textsf{hyperref}
-% and the \textsf{exframe} package:
+% Include \textsf{amsmath}, \textsf{hyperref} packages:
 %    \begin{macrocode}
 \usepackage{amsmath}
 \usepackage{hyperref}
+%    \end{macrocode}
+
+% May include \textsf{metastr} package;
+% below code adjusts to whether or not present:
+%    \begin{macrocode}
+\PassOptionsToPackage{loadlang=en|de}{metastr}
+\PassOptionsToPackage{course=true}{metastr}
+%%\usepackage{metastr}
+%%\metasetlang{de}
+%    \end{macrocode}
+
+% Include \textsf{exframe} package:
+%    \begin{macrocode}
 \usepackage[extstyle]{exframe}
 %    \end{macrocode}
 
@@ -1985,10 +2082,15 @@
 % the display of solutions near the top
 % of the source file, potentially with the opposite setting commented out:
 %    \begin{macrocode}
-\exercisesetup{solutions=true}
-%%\exercisesetup{solutions=false}
+%%\exercisesetup{solutions=true}
+\exercisesetup{solutions=false}
 %    \end{macrocode}
 
+% Automatically put labels for (sub)problems:
+%    \begin{macrocode}
+\exercisesetup{autolabelproblem=true}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Layout Declarations.}
 %
@@ -2026,8 +2128,15 @@
 % Redefine the terms to be used for sheet(s);
 % here, a German version:
 %    \begin{macrocode}
+\ifdefined\metaset
+\metasetterm[en]{sheet}{Exercise Sheet}
+\metasetterm[en]{sheets}{Exercise Sheets}
+\metasetterm[de]{sheet}{\"Ubungsblatt}
+\metasetterm[de]{sheets}{\"Ubungsbl\"atter}
+\else
 \exerciseconfig{termsheet}{\"Ubungsblatt}
 \exerciseconfig{termsheets}{\"Ubungsbl\"atter}
+\fi
 %    \end{macrocode}
 
 % Display points for problems in the margin;
@@ -2037,7 +2146,7 @@
 \exercisestyle{problempointsat=margin}
 \reversemarginpar
 \exerciseconfig{composepointsmargin}[1]{#1p.}
-\exerciseconfig{composepointspairmargin}[2]{
+\exerciseconfig{composepointspairmargin}[2]{%
   \ifdim#2pt=0pt#1p.%
   \else\ifdim#1pt=0pt+#2p.%
   \else#1+#2p.%
@@ -2068,19 +2177,35 @@
 \exercisestyle{solutionsep}
 %    \end{macrocode}
 
-% Add course name to sheet title metadata:
+% Write metadata for sheet:
 %    \begin{macrocode}
-\exerciseconfig{composemetasheet}[2]{\getexercisedata{course},
-  \exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
+\exercisesetup{pdfdata=sheet}
 %    \end{macrocode}
 
-% Set title and author for pdf metadata:
+% Set title and author for pdf metadata;
+% |title| is |course| plus |material| or sheet title;
+% |author| is |instructor| or sheet author plus |institution|:
 %    \begin{macrocode}
-\exercisesetup{pdfdata=sheet}
+\ifdefined\metaset
+\metaset[sep]{subtitle}{, }
+\metaset{subtitle}{\ifsolutions\metatranslate[#1]{solutions} \fi%
+  \metaif[use]{sheettitle}
+   {\metapick[#1]{sheettitle}}
+   {\metapick[#1]{material}}}
+\metaset{author}{\exerciseifempty{\getsheetdata{author}}%
+  {\metapick[#1]{instructor}}{\metapick[#1]{sheetauthor}},
+  \metapick[#1]{institution}}
+\else
+\exerciseconfig{composemetasheet}[2]{\getexercisedata{course},
+  \ifsolutions\getexerciseconfig{termsolutions} \fi%
+  \exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
 \exercisedata{title=%
-  {\getexercisedata{course}, \getexercisedata{material}}}
+  {\getexercisedata{course},
+  \ifsolutions\getexercisedata{solutions} \fi%
+  \getexercisedata{material}}}
 \exercisedata{author=%
   {\getexercisedata{instructor}, \getexercisedata{institution}}}
+\fi
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2088,11 +2213,21 @@
 %
 % Set some data on the current series:
 %    \begin{macrocode}
+\ifdefined\metaset
+\metaset{institution}{Katharinen-Volksschule}
+\metaset[de]{course}{Mathematik}
+\metaset[en]{course}{Mathematics}
+\metaset{instructor}{J.\ G.\ B\"uttner}
+\metaset{period}{ca.\ 1786}
+\metaset[de]{material}{\"Ubungsaufgaben}
+\metaset[en]{material}{Exercise Problems}
+\else
 \exercisedata{institution={Katharinen-Volksschule}}
 \exercisedata{course={Mathematik}}
 \exercisedata{instructor={J.\ G.\ B\"uttner}}
 \exercisedata{period={ca.\ 1786}}
 \exercisedata{material={\"Ubungsaufgaben}}
+\fi
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2104,7 +2239,7 @@
 
 % Start sheet number 5:
 %    \begin{macrocode}
-\begin{sheet}[number=5]
+\begin{sheet}[number=5,label={sheet5}]
 %    \end{macrocode}
 
 % Start a problem with a title:
@@ -2112,6 +2247,23 @@
 \begin{problem}[title={Sums},points=99+4]
 %    \end{macrocode}
 
+% Summary of points:
+%    \begin{macrocode}
+\exerciseloopstr{\getsubproblemlist{}}{c}%
+\hfill\begin{tabular}{c|\exerciseloopret|c}
+\exerciseloop{\getsubproblemlist{}}
+ {&\ref{\getexerciseconfig{labelsubproblem}{#1}}}
+&\ref{prob:\problemtag}\\\hline
+\getexerciseconfig{termpoints}
+\exerciseloop{\getsubproblemlist{}}{&\extractpoints{\getsubproblempoints{#1}}}
+&\extractpoints{\getproblempoints{}}
+\\
+extra
+\exerciseloop{\getsubproblemlist{}}{&\extractpoints*{\getsubproblempoints{#1}}}
+&\extractpoints*{\getproblempoints{}}
+\end{tabular}
+%    \end{macrocode}
+
 % Some introduction to the problem:
 %    \begin{macrocode}
 This problem deals with sums and series.
@@ -2284,6 +2436,47 @@
 \end{solution}
 %    \end{macrocode}
 
+% Summary of points per problem and per subproblem for grading:
+%    \begin{macrocode}
+\ifsolutions\else
+\textbf{Grading:}\par
+\exerciseloopstr{\getproblemlist{}}{|c}
+\begin{tabular}{|c|\exerciseloopret||c|}\hline
+\getexerciseconfig{termsheet} \ref{sheet5}
+\exerciseloop{\getproblemlist{*}}
+ {&\ref{\getexerciseconfig{labelproblem}{#1}}}
+&total
+\\\hline
+value
+\exerciseloop{\getproblemlist{*}}
+ {&\extractpoints{\getproblempoints{#1}}}%
+&\extractpoints{\getsheetpoints{}}
+\\\hline
+\exerciseloop{\getproblemlist{*}}{&}
+&\\\hline
+\end{tabular}\qquad
+\exerciseloop{\getproblemlist{*}}{
+ \exerciseloopstr{\getsubproblemlist{#1}}{|c}
+ \ifnum\value{exerciseloop}>0\relax
+  \begin{tabular}{|c|\exerciseloopret||c|}\hline
+  \getexerciseconfig{termproblem} \ref{\getexerciseconfig{labelproblem}{#1}}
+  \exerciseloop{\getsubproblemlist{#1}}
+   {&\ref{\getexerciseconfig{labelsubproblem}{##1}}}
+  &total
+  \\\hline
+  value
+  \exerciseloop{\getsubproblemlist{#1}}
+   {&\extractpoints{\getsubproblempoints{##1}}}%
+  &\extractpoints{\getproblempoints{#1}}
+  \\\hline
+  \exerciseloop{\getsubproblemlist{#1}}{&}
+  &\\\hline
+  \end{tabular}\quad
+ \fi
+}
+\fi
+%    \end{macrocode}
+
 % End sheet:
 %    \begin{macrocode}
 \end{sheet}
@@ -2342,12 +2535,13 @@
 % the document is to be compiled;
 % concretely this affects the compilations of metapost figures, see below:
 %    \begin{macrocode}
-\providecommand{\draftver}{y}
 \ifchilddoc
 \providecommand{\printsol}{y}
 \else
 \providecommand{\printsol}{n}
 \fi
+\providecommand{\draftver}{y}
+\newif\ifdraft\if\draftver y\drafttrue\else\draftfalse\fi
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2373,10 +2567,22 @@
 \PassOptionsToPackage{bookmarksopen=true}{hyperref}
 \RequirePackage{hyperref}
 %    \end{macrocode}
-% Use the \textsf{hyperxmp} package for inclusion of
-% copyright metadata in the compiled pdf files:
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{metastr Package.}
+%
+% Use the \textsf{metastr} package to handle
+% metadata and copyright information;
+% disable usage of \textsf{hyperxmp} package if not installed;
+% write auxiliary PDF metadata and rights information:
 %    \begin{macrocode}
-\IfFileExists{hyperxmp.sty}{\RequirePackage{hyperxmp}}{}
+\ifdraft
+\PassOptionsToPackage{draft}{metastr}
+\fi
+\IfFileExists{hyperxmp.sty}{}{\PassOptionsToPackage{hyperxmp=false}{metastr}}
+\RequirePackage[course]{metastr}
+\metaset[aux]{writepdf}{}
+\metaset[rights]{writepdf}{}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2388,7 +2594,9 @@
 %    \end{macrocode}
 
 % Set solutions switch and declare two-sided layout only
-% if no solutions are printed:
+% if no solutions are printed;
+% do not use solution buffer in draft mode
+% for easier identification of potential compile errors:
 %    \begin{macrocode}
 \if\printsol n
 \exercisesetup{solutions=false}
@@ -2396,7 +2604,10 @@
 \else
 \exercisesetup{solutions=true}
 \exercisesetup{twoside=false}
+\ifdraft
+\exercisesetup{solutionbuf=false}
 \fi
+\fi
 %    \end{macrocode}
 
 % Might want to display some metadata (only for partial compile):
@@ -2410,7 +2621,7 @@
 % Count problems, equations and pages by sheet
 % (unless compiling single problem).
 % Collect solutions below each problem.
-% Write pdf metadata for sheet when compiling single sheet.
+% Write pdf metadata for sheet when compiling single sheet:
 %    \begin{macrocode}
 \exercisesetup{autolabelproblem}
 \exercisestyle{contents,solutionsep}
@@ -2422,6 +2633,19 @@
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Language.}
+%
+% Redefine some terms:
+%    \begin{macrocode}
+\metasetlang{en-GB}
+
+\metasetterm[en]{sheet}{sheet}
+\metasetterm[en]{sheets}{sample sheets}
+\metasetterm[en]{solution}{Solution}
+\metasetterm[en]{solutions}{solutions}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Layout Definitions.}
 %
 % Set page dimensions and layout:
@@ -2489,16 +2713,13 @@
 % Setup \textsf{mpostinl}.
 % Use checksums to invoke metapost only when figures change.
 % Process all figures individually and immediately when in
-% draft mode (avoids a second compilation pass).
+% draft mode for child documents (avoids a second compilation pass).
 % 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| environments):
+% upon insertion/deletion of new figures or partial compilation:
 %    \begin{macrocode}
 \mpostsetup{checksum}
-\if\draftver y\mpostsetup{now,nowall}\fi
+\ifchilddoc\ifdraft\mpostsetup{now,nowall}\fi\fi
 \ifchilddocmanual\else\mpostsetup{numberwithin={sheet}}\fi
-\ifsolutions\else\mpostsetup{warnunused=false}\fi
 %    \end{macrocode}
 
 % Global metapost definitions.
@@ -2508,7 +2729,9 @@
 % |paths| is an array of path variables,
 % |xu| serves as a length unit to
 % scale individual figures
-% (use |interim xu:=...;| to set scale for local figure only):
+% (use |interim xu:=...;| to set scale for local figure only),
+% |pensize| changes the size of the pen,
+% |fillshape| fills and outlines a shape:
 %    \begin{macrocode}
 \mpostsetup{globaldef=true}
 \begin{mposttex}
@@ -2518,6 +2741,11 @@
 path paths[];
 newinternal numeric xu;
 xu:=1cm;
+def pensize(expr s)=withpen pencircle scaled s enddef;
+def fillshape(expr p,c)=
+  fill p withcolor c;
+  draw p
+enddef;
 \end{mpostdef}
 \mpostsetup{globaldef=false}
 %    \end{macrocode}
@@ -2532,99 +2760,64 @@
 %
 % Set document data for series of problem sheets:
 %    \begin{macrocode}
-\exercisedata{course={exframe package samples}}
-\exercisedata{instructor={N.\ Beisert}}
-\exercisedata{institution={exframe academy}}
-\exercisedata{period={spring 2019}}
-\exercisedata{date={2019}}
+\metaset{course}{exframe package samples}
+\metaset{instructor}{N.\ Beisert}
+\metaset{author}{Niklas Beisert, \metapick[#1]{institution}}
+\metaset{institution}{exframe academy}
+\metaset{period}{spring 2019}
+\metaset{copyrightdate}{2019--2020}
 %    \end{macrocode}
 
 % Assemble some entries from given data:
 %    \begin{macrocode}
-\exercisedata{material={\ifsolutions\getexerciseconfig{termsolutions}%
-  \else\getexerciseconfig{termsheets}\fi}}
+\metaset{material}{\metatranslate[#1]{sheets}}
 \exerciseconfig{composetitlesheet}[2]{\exerciseifempty{#2}%
-  {\ifsolutions\getexerciseconfig{termsolutions}\else%
-   \getexerciseconfig{termsheet}\fi\ #1}%
-  {\ifsolutions\getexerciseconfig{termsolutions}\fi\ #2}}
-\exerciseconfig{composemetasheet}[2]{\if\draftver yDRAFT: \fi%
-  \getexercisedata{course},
-  \getexerciseconfig{composetitlesheet}{#1}{#2}}
+  {\ifsolutions\metaterm{solutions}\else%
+   \metaterm{sheet}\fi\ #1}%
+  {\ifsolutions\metaterm{solutions} \fi #2}}
 %    \end{macrocode}
 
-% Set general purpose metadata:
+% For child documents declare part of:
 %    \begin{macrocode}
-\exercisedata{title={\if\draftver yDRAFT: \fi%
-  \getexercisedata{course}, \getexercisedata{material}}}
-\exercisedata{author={Niklas Beisert, \getexercisedata{institution}}}
-\exercisedata{subject={lecture series at \getexercisedata{institution},
-  \getexercisedata{period}}}
+\ifchilddoc
+\metaset{partof}{\metatranslate[#1]{sheets} \metapick[#1]{course}}
+\fi
 %    \end{macrocode}
 
-% Redefine some terms:
+% Set general purpose metadata:
 %    \begin{macrocode}
-\exerciseconfig{termsheet}{sheet}
-\exerciseconfig{termsheets}{sample sheets}
-\exerciseconfig{termsolution}{Solution}
-\exerciseconfig{termsolutions}{solutions}
+\metaset[sep]{draft}{ -- }
+\metaset[sep]{subtitle}{, }
+\metaset{subtitle}{\ifsolutions\metatranslate[#1]{solutions} \fi%
+  \metaif[use]{sheettitle}{\metapick[#1]{sheettitle}}{\metapick[#1]{material}}}
+\metaset{subject}{Lecture Series,
+  \metapick[#1]{institution}, \metapick[#1]{period}}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{License.}
 %
-% It is always useful to specify a copyright line
-% and a license for the document.
-% Define some restrictive default text.
+% It is good practice to specify a copyright line
+% and a license for the document:
 %    \begin{macrocode}
-\def\copyrightmessage
-  {This document as well as its parts is protected by copyright.}
-\def\licensemessage
-  {Reproduction of any part of this work in any form
-  without prior written consent of \getexercisedata{institution}
-  is not permissible.}
+\metaset{copyrightowner}{\metapick[#1]{author}}
+\ifchilddoc
+\metacopyright{doc}
+\else
+\metacopyright{doc-parts}
+\fi
+\metaset{licenseprovider}{of \metapick[#1]{institution}}
+\metalicense{consent}
 %    \end{macrocode}
 
 % Apply Creative Commons BY-SA license
 % under certain conditions (no solutions, final version):
 %    \begin{macrocode}
-\ifsolutions\else\if\draftver y\else
-\def\licensecctype{by-sa}
-\def\licenseccname{Attribution-ShareAlike \licenseccver{} International}
+\ifsolutions\else\ifdraft\else
+\metalicensecc{by-sa}
 \fi\fi
 %    \end{macrocode}
 
-% Write applicable Creative Commons license information.
-% Use Creative Commons logos included in package \textsf{doclicense}:
-%    \begin{macrocode}
-\ifdefined\licensecctype
-\ifdefined\licenseccver\else\def\licenseccver{4.0}\fi
-\def\licenseurl
-  {https://creativecommons.org/licenses/\licensecctype/\licenseccver}
-\def\licensemessage{\texorpdfstring
-  {This work is licensed under the Creative Commons ``\licenseccname'' License
-  (CC \MakeUppercase{\licensecctype} \licenseccver).\par
-  \IfFileExists{doclicense.sty}{
-   \begin{center}\includegraphics{doclicense-CC-\licensecctype}\end{center}}{}
-  To view a copy of this license, visit: \url{\licenseurl}}
-  {This work is licensed under the Creative Commons \licenseccname{} License.}}
-\fi
-%    \end{macrocode}
-
-% Write copyright and license as pdf metadata
-% (using package \textsf{hyperxmp} if available):
-%    \begin{macrocode}
-\ifdefined\xmptilde
-\hypersetup{pdfcopyright={Copyright \getexercisedata{date}
-  \getexercisedata{author}. \copyrightmessage{} \licensemessage}}
-\ifdefined\sourceurl\hypersetup{pdflicenseurl={\sourceurl}}\else
-\ifdefined\licenseurl\hypersetup{pdflicenseurl={\licenseurl}}\fi\fi
-\hypersetup{keeppdfinfo=true}
-\hypersetup{pdfsource={}}
-\XMPLangAlt{en}{pdfcopyright={Copyright \getexercisedata{date}
-  \getexercisedata{author}. \copyrightmessage{} \licensemessage}}
-\fi
-%    \end{macrocode}
-
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Body.}
 %
@@ -2660,18 +2853,11 @@
 
 % Prepare a title page to display some relevant data:
 %    \begin{macrocode}
-\pdfbookmark[1]{Title Page}{title}
+\pdfbookmark[1]{\metaterm{title}}{title}
 \thispagestyle{empty}
 \vspace*{\fill}
 \begin{center}
-\begingroup\bfseries\LARGE\getexercisedata{course}\par\endgroup
-\vspace{0.5cm}
-\begingroup\large\getexercisedata{material}\par\endgroup
-\vspace{0.5cm}
-\begingroup\large\getexercisedata{institution},
-  \getexercisedata{period}\par\endgroup
-\vspace{2cm}
-\begingroup\scshape\Large\getexercisedata{instructor}\par\endgroup
+\metapick[course]{titletext}
 \end{center}
 \vspace*{\fill}\vspace*{\fill}
 \newpage
@@ -2679,17 +2865,11 @@
 
 % Prepare a copyright and license page using data specified above:
 %    \begin{macrocode}
-\phantomsection\pdfbookmark[1]{Copyright}{copyright}
+\phantomsection\pdfbookmark[1]{\metaterm{copyright}}{copyright}
 \thispagestyle{empty}
 \vspace*{\fill}\vspace*{\fill}
-\begin{center}
-\begin{minipage}{11cm}\raggedright
-{\copyright} \getexercisedata{date} \getexercisedata{author}
-\par\medskip
-\copyrightmessage{}
-\licensemessage
-\ifdefined\sourcemessage\par\medskip\sourcemessage\fi
-\ifdefined\attributionmessage\par\medskip\attributionmessage\fi
+\begin{center}\begin{minipage}{11cm}\raggedright
+\metapick[print]{rightstext}
 \end{minipage}\end{center}
 \vspace*{\fill}\vspace*{\fill}\vspace*{\fill}
 \newpage
@@ -2699,7 +2879,7 @@
 %    \begin{macrocode}
 \makeatletter\renewcommand\@pnumwidth{2.4em}\makeatother
 \setcounter{tocdepth}{2}
-\phantomsection\pdfbookmark[1]{Contents}{contents}
+\phantomsection\pdfbookmark[1]{\metaterm{contents}}{contents}
 {\parskip0pt\tableofcontents}
 \exercisecleardoublepage\setcounter{page}{1}
 %    \end{macrocode}
@@ -2810,16 +2990,26 @@
 % where \textit{tag} is the tag of the problem
 % (in order to avoid potential conflicts with other problems;
 % \textit{tag} is assigned automatically or by specifying
-% the option |tag| for the |problem| environment):
+% the option |tag| for the |problem| environment).
+% Also declare a figure \textit{tag}|-solfig| for use within the solution:
 %    \begin{macrocode}
 \ifdefined\mpostuse
 \begin{mpostfig}[label={\problemtag-fig}]
 interim xu:=1.5cm;
 paths[1]:=fullcircle scaled 1xu;
-fill paths[1] withgreyscale 0.7;
-draw paths[1] withpen pencircle scaled 1pt;
+fillshape(paths[1], 0.7white) pensize(1pt);
 label(btex \figure etex, center(paths[1]));
 \end{mpostfig}
+\begin{onlysolutions}
+\begin{mpostfig}[label={\problemtag-solfig}]
+interim xu:=1.5cm;
+paths[1]:=fullcircle scaled 1xu;
+paths[2]:=((subpath (-2,2) of paths[1])--cycle) shifted (+0.5xu,0);
+paths[3]:=((subpath (2,6) of paths[1])--cycle) shifted (-0.5xu,0);
+fillshape(paths[2], 0.7white) pensize(1pt);
+fillshape(paths[3], 0.7white) pensize(1pt);
+\end{mpostfig}
+\end{onlysolutions}
 \fi
 %    \end{macrocode}
 
@@ -2837,6 +3027,10 @@
 
 \begin{solution}
 \lorem
+\begin{center}
+\ifdefined\mpostuse\mpostuse{\problemtag-solfig}\else figure\fi
+\end{center}
+\lorem
 \end{solution}
 
 \begin{subproblem}
@@ -3096,7 +3290,7 @@
     fwd="\\childdocforward[$srcmain]{$srcsec$num}"
   fi
   body="\\def\\jobname{$job}$optdef\\input{childdoc.def}$fwd"
-  for pass in first main
+  for pass in first main extra
   do
     par="";
     if [[ "$pass" == "first" ]]; then par="-draftmode"; fi
@@ -3105,7 +3299,8 @@
     pdflatex -shell-escape -interaction=batchmode $par \
       -jobname "$trg" "$body" | grep -vE "$drop"
     if [[ "$pass" != "main" ]]; then continue; fi
-    if ! (grep -E -q "may have changed|rerunfilecheck Warning" "$trg.log"); then break; fi
+    if ! (grep -E -q "may have changed|rerunfilecheck Warning" "$trg.log")
+      then break; fi
   done
   grep -E "^! |Warning|Error|Undefined|Overfull|Underfull" "$trg.log"
 }
@@ -3185,7 +3380,8 @@
 TRGMAINFILES = $(foreach trg,$(TRGLIST),$(trg).pdf)
 TRGSECFILES = $(foreach trg,$(TRGLIST),$(trg).pdf $(SECNUM:%=$(trg)%.pdf))
 GENFILES = $(foreach trg,$(TRGLIST),$(trg).tex $(SECNUM:%=$(trg)%.tex))
-BAKFILES = $(PREREQS) $(SRCSECFILES) $(GENFILES) $(MAKEFILE) $(SCRIPT) $(SRCPRB)*
+BAKFILES = $(PREREQS) $(SRCSECFILES) $(GENFILES)\
+           $(MAKEFILE) $(SCRIPT) $(SRCPRB)*
 %    \end{macrocode}
 %\iffalse$\fi
 
@@ -3228,12 +3424,12 @@
 	rm -f $(foreach ext,.aux .log,$(SECNUM:%=$(SRCSEC)%$(ext)))
 	rm -f $(foreach trg,$(TRGLIST),$(SECNUM:%=$(trg)%.log) $(trg).log)
 	rm -f $(foreach ext,.aux .log .out .toc,$(SRCMAIN)$(ext))
-	rm -f $(foreach ext,.mp .mpx -*.mps -tmp.log -tmp.mp -tmp.mpx,$(SRCMAIN)$(ext))
+	rm -f $(foreach ext,.mp .mpx -*.mps,$(SRCMAIN)$(ext))
+	rm -f $(foreach ext,-tmp.log -tmp.mp -tmp.mpx,$(SRCMAIN)$(ext))
 	rm -f mpxerr.tex mpxerr.log mpxerr.dvi texput.log
 	rm -f $(patsubst %,$(SRCPRB)*%,.aux .log .mp .mpx -*.mps)
 	rm -f $(patsubst %,$(SRCPRB)*%,-tmp.log -tmp.mp -tmp.mpx)
 %    \end{macrocode}
-%\iffalse$\fi
 % Define |clean-bak| target to remove all backup files
 % ending in `|~|' or `|.bak|':
 %    \begin{macrocode}
@@ -3317,6 +3513,11 @@
 \def\exf at csdo#1#2{\expandafter#1\csname#2\endcsname}
 \def\exf at csdotwo#1#2#3{\exf at exptwo#1#2\csname#3\endcsname}
 %    \end{macrocode}
+% \macro{\exf at csor}
+% A macro to return |\csname| or default if not exists:
+%    \begin{macrocode}
+\def\exf at csor#1#2{\ifcsname#1\endcsname\csname#1\endcsname\else#2\fi}
+%    \end{macrocode}
 
 % \macro{\exf at append@def}
 % \macro{\exf at prepend@def}
@@ -3370,6 +3571,26 @@
   \ifx#1\exf at empty\else\addcontentsline{toc}{#1}{#2}\fi}
 %    \end{macrocode}
 
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Auxiliary File Data Storage.}
+%
+% \macro{\exf at notedata}
+% Process stored data by handler:
+%    \begin{macrocode}
+\newcommand{\exf at notedata}[3]{\csname exf at notedata@#1\endcsname{#2}{#3}}
+%    \end{macrocode}
+% Make sure the macros in code written to the |.aux| file exist:
+%    \begin{macrocode}
+\AtBeginDocument{\immediate\write\@auxout{%
+  \string\providecommand{\string\exf at notedata}[3]{}}}
+%    \end{macrocode}
+% \macro{\exf at writedata}
+% Write data to the |.aux| file:
+%    \begin{macrocode}
+\newcommand{\exf at writedata}[3]%
+  {\immediate\write\@auxout{\string\exf at notedata{#1}{#2}{#3}}}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \subsection{Package Setup}
 % \label{sec:imp-setup}
@@ -3407,6 +3628,12 @@
 \define at boolkey{exframe.sty}[exf@]{extstyle}[true]{}
 %    \end{macrocode}
 
+% Whether to load package \textsf{metastr}
+% (available while loading only):
+%    \begin{macrocode}
+\define at boolkey{exframe.sty}[exf@]{metastr}[true]{}
+%    \end{macrocode}
+
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Setup Options.}
 %
@@ -3455,6 +3682,12 @@
 %    \begin{macrocode}
 \define at boolkey{exf at setup}[exf@]{problembuf}[true]{}
 %    \end{macrocode}
+% \macro{\exf at emptytestchar}
+% Redefine character for testing emptyness:
+%    \begin{macrocode}
+\def\exf at emptytestchar{&}
+\define at key{exf at setup}{emptytestchar}{\def\exf at emptytestchar{#1}}
+%    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Processing.}
@@ -3471,6 +3704,17 @@
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Additional Packages.}
+%
+% Load \textsf{metastr} package if desired:
+%    \begin{macrocode}
+\ifexf at metastr
+\PassOptionsToPackage{course=true}{metastr}
+\RequirePackage{metastr}
+\fi
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Solutions Only Processing.}
 %
 % \macro{onlysolutions}
@@ -3534,8 +3778,10 @@
 % Code to test whether |#1| (expanded) is empty;
 % execute |#2| if empty, otherwise execute |#3|:
 %    \begin{macrocode}
-\long\def\exerciseifempty#1#2#3{\if&#1&#2\else#3\fi}
-\long\def\exerciseifnotempty#1#2{\if&#1&\else#2\fi}
+\long\def\exerciseifempty#1#2#3{%
+  \if\exf at emptytestchar#1\exf at emptytestchar#2\else#3\fi}
+\long\def\exerciseifnotempty#1#2{%
+  \if\exf at emptytestchar#1\exf at emptytestchar\else#2\fi}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -4041,12 +4287,24 @@
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Further Definitions.}
 %
+% \macro{tagsheet}
+% \macro{tagproblem}
+% \macro{tagsubproblem}
+% Templates for automatic generation of tags:
+%    \begin{macrocode}
+\exerciseconfig{tagsheet}{\arabic{\exf at sheetcounter}}
+\exerciseconfig{tagproblem}{\csname the\exf at problemcounter\endcsname}
+\exerciseconfig{tagsubproblem}{\problemtag-\arabic{\exf at subproblemcounter}}
+%    \end{macrocode}
+
 % \macro{labelsheet}
 % \macro{labelproblem}
+% \macro{labelsubproblem}
 % Templates for automatic generation of labels from tags:
 %    \begin{macrocode}
 \exerciseconfig{labelsheet}[1]{sheet:#1}
 \exerciseconfig{labelproblem}[1]{prob:#1}
+\exerciseconfig{labelsubproblem}[1]{\getexerciseconfig{labelproblem}{#1}}
 %    \end{macrocode}
 
 % \macro{toclevel...}
@@ -4576,23 +4834,20 @@
     \hypersetup{pdfsubject={\exf at data@subject}}\fi%
    \ifx\exf at data@keyword\exf at empty\else%
     \hypersetup{pdfkeywords={\exf at data@keyword}}\fi%
-  \fi%
+  \fi}
 %    \end{macrocode}
-% Do not write again:
-%    \begin{macrocode}
-  \gdef\exf at metadata{off}}
-%    \end{macrocode}
 
 % Automatic writing at |\begin{document}|:
 %    \begin{macrocode}
-\AtBeginDocument{\exf at ifis\exf at metadata{auto}{\exf at writemetadata}}
+\AtBeginDocument{\exf at ifis\exf at metadata{auto}%
+  {\exf at writemetadata\gdef\exf at metadata{off}}}
 %    \end{macrocode}
 
 % \macro{\writeexercisedata}
 % Write metadata manually:
 %    \begin{macrocode}
-\newcommand{\writeexercisedata}{%
-  \exf at ifis\exf at metadata{manual}{\exf at writemetadata}}
+\newcommand{\writeexercisedata}{\exf at ifis\exf at metadata{manual}%
+  {\exf at writemetadata\gdef\exf at metadata{off}}}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -4636,7 +4891,15 @@
 \newcommand{\exf at numberproblemwithin}[1]{%
   \@addtoreset{\exf at problemcounter}{#1}%
   \exf at csdo\def{the\exf at problemcounter}%
-   {\csname the#1\endcsname.\exf at config@counterproblem}}
+   {\csname the#1\endcsname.\exf at config@counterproblem}%
+  \edef\exf at tmp{#1}%
+  \ifx\exf at tmp\exf at sheetcounter%
+   \exerciseconfig{tagproblem}{\ifdefined\sheettag\sheettag-\fi%
+    \arabic{\exf at problemcounter}}%
+  \else%
+   \exerciseconfig{tagproblem}{\csname the#1\endcsname-%
+    \arabic{\exf at problemcounter}}%
+  \fi}
 %    \end{macrocode}
 
 % \macro{\exf at numberequationwithin}
@@ -4917,13 +5180,13 @@
 %    \end{macrocode}
 
 % \macro{\exf at scanpoints}
-% Call as |\exf at scanpoints#1|[\textit{regular}][|+|\textit{bonus}]|++&| to
+% Call as |\exf at scanpoints#1|[\textit{regular}][|+|\textit{bonus}]|++@| to
 % write |{|\textit{regular}|}{|\textit{bonus}|}| into |#1|;
 % fill with 0 if empty:
 %    \begin{macrocode}
-\def\exf at scanpoints#1#2+#3+#4&{%
-  \edef#1{\if&#2&0\else#2\fi}%
-  \edef#1{{#1}{\if&#3&0\else#3\fi}}}
+\def\exf at scanpoints#1#2+#3+#4@{%
+  \edef#1{\if @#2 at 0\else#2\fi}%
+  \edef#1{{#1}{\if @#3 at 0\else#3\fi}}}
 %    \end{macrocode}
 % \macro{\exf at formatpoints}
 % Format as [|#1|][|+#2|]; remove 0 components:
@@ -4938,7 +5201,7 @@
 \newcommand{\extractpoints}{\@ifstar{\exf at extractpoints\@secondoftwo}%
   {\exf at extractpoints\@firstoftwo}}
 \newcommand{\exf at extractpoints}[2]{\edef\exf at tmp{#2}%
-  \exf at exptwo\exf at scanpoints\exf at tmp\exf at tmp++&%
+  \exf at exptwo\exf at scanpoints\exf at tmp\exf at tmp++@%
   \expandafter#1\exf at tmp}
 %    \end{macrocode}
 
@@ -4947,7 +5210,7 @@
 % 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++&%
+  \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}%
@@ -5016,8 +5279,8 @@
   \edef\exf at tmp{#1}%
   \expandafter\exf at splitsign\exf at tmp--&%
   \expandafter\exf at splitdecimal\exf at splitnum..&%
-  \if&\exf at splitint&\def\exf at splitint{0}\fi%
-  \if&\exf at splitdec&\def\exf at splitdec{0}\fi%
+  \if @\exf at splitint @\def\exf at splitint{0}\fi%
+  \if @\exf at splitdec @\def\exf at splitdec{0}\fi%
   \def\exf at tmp{\exf at splitint.\exf at splitdec}%
   \ifnum\exf at splitdec=0\def\exf at tmp{\exf at splitint}\fi%
   \ifnum\exf at splitdec=5\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{2}}\fi%
@@ -5036,8 +5299,8 @@
 % such as 12$^3\mskip-4mu/\mskip-2mu_4$:
 %    \begin{macrocode}
 \newcommand{\exf at config@frac}[3]{%
-  \ifnum#1=0\else#1\fi%
-  \ifnum#2=0\else$%
+  \ifnum#1=0\relax\else#1\fi%
+  \ifnum#2=0\relax\else$%
    ^{\exf at text{#2}}%
    \mskip-4mu/\mskip-2mu%
    _{\exf at text{#3}}$\fi}
@@ -5046,72 +5309,50 @@
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Sheet Points Code.}
 %
-% \macro{\exf at notesheetpoints}
+% \macro{\exf at notedata@sheetpoints}
 % Store a sheet point number in a macro:
 %    \begin{macrocode}
-\newcommand{\exf at notesheetpoints}[2]{%
+\newcommand{\exf at notedata@sheetpoints}[2]{%
   \exf at csdo\gdef{exf at sheetpoints@#1}{#2}}
 %    \end{macrocode}
-% Make sure the macros in code written to the |.aux| file exist:
-%    \begin{macrocode}
-\AtBeginDocument{\immediate\write\@auxout{%
-  \string\providecommand{\string\exf at notesheetpoints}[2]{}}}
-%    \end{macrocode}
 % \macro{\exf at writesheetpoints}
 % Write sheet points to the |.aux| file:
 %    \begin{macrocode}
 \newcommand{\exf at writesheetpoints}[2]%
-  {\immediate\write\@auxout{\string\exf at notesheetpoints{\sheettag}%
-   {\exf at formatpoints{#1}{#2}}}}
+  {\exf at writedata{sheetpoints}{\sheettag}{\exf at formatpoints{#1}{#2}}}
 %    \end{macrocode}
 % \macro{\getsheetpoints}
 % Read points for current sheet or from |.aux| file:
 %    \begin{macrocode}
-\newcommand{\getsheetpoints}[1]{\if&#1&%
+\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}
+  \else\exf at csor{exf at sheetpoints@#1}{0}\fi}
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Problem Points Code.}
 %
-% \macro{\exf at noteproblempoints}
+% \macro{\exf at notedata@problempoints}
 % Store a problem point number in a macro:
 %    \begin{macrocode}
-\newcommand{\exf at noteproblempoints}[2]{%
+\newcommand{\exf at notedata@problempoints}[2]{%
   \exf at csdo\gdef{exf at problempoints@#1}{#2}}
 %    \end{macrocode}
-% Make sure the macros written to the |.aux| file exist:
-%    \begin{macrocode}
-\AtBeginDocument{\immediate\write\@auxout{%
-  \string\providecommand{\string\exf at noteproblempoints}[2]{}}}
-%    \end{macrocode}
 % \macro{\exf at writeproblempoints}
 % Write problem points to the |.aux| file:
 %    \begin{macrocode}
 \newcommand{\exf at writeproblempoints}[2]%
-  {\immediate\write\@auxout{\string\exf at noteproblempoints{\problemtag}%
-   {\exf at formatpoints{#1}{#2}}}}
+  {\exf at writedata{problempoints}{\problemtag}{\exf at formatpoints{#1}{#2}}}
 %    \end{macrocode}
 % \macro{\getproblempoints}
 % Read points for current problem or from |.aux| file:
 %    \begin{macrocode}
-\newcommand{\getproblempoints}[1]{\if&#1&%
+\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}
+  \else\exf at csor{exf at problempoints@#1}{0}\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:
@@ -5127,6 +5368,31 @@
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Subproblem Points Code.}
+%
+% \macro{\exf at notedata@subproblempoints}
+% Store a subproblem point number in a macro:
+%    \begin{macrocode}
+\newcommand{\exf at notedata@subproblempoints}[2]{%
+  \exf at csdo\gdef{exf at subproblempoints@#1}{#2}}
+%    \end{macrocode}
+% \macro{\exf at writesubproblempoints}
+% Write subproblem points to the |.aux| file:
+%    \begin{macrocode}
+\newcommand{\exf at writesubproblempoints}[2]%
+  {\exf at writedata{subproblempoints}%
+   {\subproblemtag}{\exf at formatpoints{#1}{#2}}}
+%    \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\exf at csor{exf at subproblempoints@#1}{0}\fi}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \paragraph{Solution Points Code.}
 %
 % \macro{\exf at awardpointsalt}
@@ -5133,7 +5399,7 @@
 % Award points for alternative or optional solution;
 % does not count towards solution total:
 %    \begin{macrocode}
-\newcommand{\exf at awardpointsalt}[2][]{\exf at scanpoints\exf at tmp#2++&%
+\newcommand{\exf at awardpointsalt}[2][]{\exf at scanpoints\exf at tmp#2++@%
   \exf at exptwo\exf at ensuretext{%
    \expandafter\exf at config@composepointspairawardalt\exf at tmp{#1}}}
 %    \end{macrocode}
@@ -5141,9 +5407,9 @@
 % Award points for regular solution;
 % counts towards solution total:
 %    \begin{macrocode}
-\newcommand{\exf at awardpointsreg}[2][]{\exf at scanpoints\exf at tmp#2++&%
+\newcommand{\exf at awardpointsreg}[2][]{\exf at scanpoints\exf at tmp#2++@%
   \exf at exptwo\exf at addtopoints\exf at solution@points at total\exf at tmp%
-  \exf at scanpoints\exf at tmp#2++&%
+  \exf at scanpoints\exf at tmp#2++@%
   \exf at exptwo\exf at ensuretext{%
    \expandafter\exf at config@composepointspairaward\exf at tmp{#1}}}
 %    \end{macrocode}
@@ -5156,7 +5422,7 @@
 % \macro{\getsolutionpoints}
 % Read points for current solution:
 %    \begin{macrocode}
-\newcommand{\getsolutionpoints}[1]{\if&#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}
@@ -5163,6 +5429,107 @@
 %    \end{macrocode}
 
 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Tag Lists}
+% \label{sec:imp-taglist}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Loop Lists.}
+%
+% \macro{exerciseloop}
+% \macro{exf at loopdepth}
+% Counters for item number within list and depth of loop nesting:
+%    \begin{macrocode}
+\newcounter{exerciseloop}
+\newcounter{exf at loopdepth}
+%    \end{macrocode}
+
+% \macro{exf at listwalk}
+% Step through a list;
+% call the callback function |#1| with current item |#2|:
+%    \begin{macrocode}
+\def\exf at listwalk#1#2{\if @#2@\def\exf at tmp{}\else%
+  \def\exf at tmp{#1{#2}\exf at listwalk#1}\fi\exf at tmp}
+%    \end{macrocode}
+
+% \macro{\exerciseloop}
+% Loop through a list of items in braces |#1|
+% which is expanded first;
+% store code |#2| to be executed in a callback function
+% (need to use different callback function for each loop depth,
+% callback function must be global to work within table cells);
+% initialise item counter:
+%    \begin{macrocode}
+\newcommand{\exerciseloop}[2]{\addtocounter{exf at loopdepth}{1}%
+  \setcounter{exerciseloop}{0}%
+  \exf at csdo\gdef{exf at listcallback@\roman{exf at loopdepth}}##1%
+   {\stepcounter{exerciseloop}#2}%
+  \edef\exf at tmp{#1}%
+  \exf at csdotwo\exf at exptwo\exf at listwalk%
+   {exf at listcallback@\roman{exf at loopdepth}}\exf at tmp{}%
+  \addtocounter{exf at loopdepth}{-1}}
+%    \end{macrocode}
+% \macro{\exerciseloopstr}
+% Loop through list and save result to |\exerciseloopret|
+% (or optional argument |#1|):
+%    \begin{macrocode}
+\newcommand{\exerciseloopstr}[3][\exerciseloopret]{%
+  \def#1{}\exerciseloop{#2}{\protected at edef#1{#1#3}}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Lists Management.}
+%
+% \macro{\exf at notedata@sheet}
+% Store a sheet tag:
+%    \begin{macrocode}
+\def\exf at sheetlist{}
+\newcommand{\exf at notedata@sheet}[2]{%
+  \xdef\exf at sheetlist{\exf at sheetlist{#1}}}
+%    \end{macrocode}
+% \macro{\exf at notedata@problem}
+% Store a problem tag:
+%    \begin{macrocode}
+\def\exf at problemlist{}
+\newcommand{\exf at notedata@problem}[2]{%
+  \xdef\exf at problemlist{\exf at problemlist{#1}}%
+  \if @#2@\else%
+   \ifcsname exf at problemlist@#2\endcsname\else%
+    \exf at csdo\gdef{exf at problemlist@#2}{}\fi%
+   \exf at csdo\xdef{exf at problemlist@#2}%
+    {\csname exf at problemlist@#2\endcsname{#1}}%
+  \fi}
+%    \end{macrocode}
+% \macro{\exf at notedata@subproblem}
+% Store a subproblem tag:
+%    \begin{macrocode}
+\newcommand{\exf at notedata@subproblem}[2]{%
+  \ifcsname exf at subproblemlist@#2\endcsname\else%
+   \exf at csdo\gdef{exf at subproblemlist@#2}{}\fi%
+  \exf at csdo\xdef{exf at subproblemlist@#2}%
+   {\csname exf at subproblemlist@#2\endcsname{#1}}}
+%    \end{macrocode}
+
+% \macro{\getsheetlist}
+% \macro{\getproblemlist}
+% \macro{\getsubproblemlist}
+% Get list of sheet tags,
+% problem tags (all, within current or particular sheet),
+% subproblem tags (within current or particular problem):
+%    \begin{macrocode}
+\newcommand{\getsheetlist}[1]{\exf at sheetlist}
+\newcommand{\getproblemlist}[1]{\if @#1@%
+  \ifdefined\sheettag\exf at csor{exf at problemlist@\sheettag}{}%
+  \else\exf at problemlist\fi%
+ \else%
+  \if *#1\exf at problemlist\else\exf at csor{exf at problemlist@#1}{}\fi%
+ \fi}
+\newcommand{\getsubproblemlist}[1]{\if @#1@%
+  \exf at csor{exf at subproblemlist@\problemtag}{}\else%
+  \exf at csor{exf at subproblemlist@#1}{}\fi}
+%    \end{macrocode}
+
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % \subsection{Sheet Environment}
 % \label{sec:imp-sheet}
 %
@@ -5169,8 +5536,9 @@
 % \macro{exf at sheet}
 % Define options for |sheet| environment:
 %    \begin{macrocode}
-\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}{points}{\exf at scanpoints\exf at sheet@points#1++@}
+\define at key{exf at sheet}{number}{\setcounter{\exf at sheetcounter}{#1}%
+  \addtocounter{\exf at sheetcounter}{-1}\refstepcounter{\exf at sheetcounter}}
 \define at key{exf at sheet}{label}{\def\exf at label{#1}}
 \define at key{exf at sheet}{tag}{\def\sheettag{#1}}
 %    \end{macrocode}
@@ -5197,7 +5565,7 @@
 % Reset optional arguments, process arguments:
 %    \begin{macrocode}
   \let\exf at sheet@points\@undefined%
-  \def\sheettag{\csname the\exf at sheetcounter\endcsname}%
+  \def\sheettag{\getexerciseconfig{tagsheet}}%
   \let\exf at sheet@points at total\@undefined%
   \let\exf at label\@undefined%
   \setkeys{exf at sheet}{#1}%
@@ -5206,6 +5574,7 @@
 %    \begin{macrocode}
   \ifexf at autolabelsheet\label{\exf at config@labelsheet{\sheettag}}\fi%
   \ifdefined\exf at label\label{\exf at label}\fi%
+  \exf at writedata{sheet}{\sheettag}{}%
 %    \end{macrocode}
 % Set points from explicit input or from |.aux| storage:
 %    \begin{macrocode}
@@ -5215,7 +5584,7 @@
    \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++&%
+    \exf at exptwo\exf at scanpoints\exf at sheet@points\exf at tmp++@%
   \fi\fi%
 %    \end{macrocode}
 % Process metadata:
@@ -5225,7 +5594,7 @@
     \let\exf at data@author\exf at data@sheet at author\fi%
    \def\exf at data@title{\exf at config@composemetasheet%
     {\csname the\exf at sheetcounter\endcsname}{\exf at data@sheet at rawtitle}}%
-   \exf at writemetadata}}%
+   \exf at writemetadata}\gdef\exf at metadata{off}}%
 %    \end{macrocode}
 % Insert hook code:
 %    \begin{macrocode}
@@ -5306,7 +5675,7 @@
 % \macro{exf at problem}
 % Define options for |problem| environment:
 %    \begin{macrocode}
-\define at key{exf at problem}{points}{\exf at scanpoints\exf at problem@points#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}}
@@ -5346,7 +5715,7 @@
 % Initialise variables, process arguments:
 %    \begin{macrocode}
   \exf at init@block{\exf at config@skipprobleminfo}%
-  \def\problemtag{\csname the\exf at problemcounter\endcsname}%
+  \def\problemtag{\getexerciseconfig{tagproblem}}%
   \let\exf at problem@points\@undefined%
   \let\exf at label\@undefined%
   \global\let\exf at sollabel\@undefined%
@@ -5357,6 +5726,7 @@
 %    \begin{macrocode}
   \ifexf at autolabelproblem\label{\exf at config@labelproblem{\problemtag}}\fi%
   \ifdefined\exf at label\label{\exf at label}\fi%
+  \exf at writedata{problem}{\problemtag}{\ifdefined\sheettag\sheettag\fi}%
 %    \end{macrocode}
 % Mark for new solution section; remember problem counter, title:
 %    \begin{macrocode}
@@ -5382,7 +5752,7 @@
    \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++&%
+    \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%
@@ -5490,8 +5860,10 @@
   \ifdefined\exf at problem@points%
    \expandafter\exf at writeproblempoints\exf at problem@points%
    \exf at exptwo\exf at addtopoints\exf at sheet@points at total\exf at problem@points%
-  \fi%
-  \ifdefined\exf at problem@points\else\ifdefined\exf at sheet@points at total%
+%    \end{macrocode}
+% Warn if no points given for present problem but previously:
+%    \begin{macrocode}
+  \else\ifdefined\exf at sheet@points at total%
    \PackageWarning{exframe}{no points defined for \exf at problemname}%
   \fi\fi%
 %    \end{macrocode}
@@ -5743,8 +6115,9 @@
 % \macro{exf at subproblem}
 % Define options for |subproblem| environment:
 %    \begin{macrocode}
-\define at key{exf at subproblem}{points}{\exf at scanpoints\exf at subproblem@points#1++&}
+\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}}
+\define at key{exf at subproblem}{tag}{\def\subproblemtag{#1}}
 %    \end{macrocode}
 
 % \macro{subproblem}
@@ -5769,13 +6142,17 @@
 % Initialise variables, process arguments:
 %    \begin{macrocode}
   \exf at init@block{\exf at config@skipsubprobleminfo}%
+  \def\subproblemtag{\getexerciseconfig{tagsubproblem}}%
   \let\exf at subproblem@points\@undefined%
   \let\exf at label\@undefined%
   \setkeys{exf at subproblem,exf at probleminfo}{#1}%
 %    \end{macrocode}
-% Process manual label:
+% Process automatic and manual labels:
 %    \begin{macrocode}
+  \ifexf at autolabelproblem\label{\exf at config@labelsubproblem%
+   {\subproblemtag}}\fi%
   \ifdefined\exf at label\label{\exf at label}\fi%
+  \exf at writedata{subproblem}{\subproblemtag}{\problemtag}%
 %    \end{macrocode}
 % Remember subproblem counter for solution:
 %    \begin{macrocode}
@@ -5785,7 +6162,7 @@
     \csname theH\exf at subproblemcounter\endcsname}%
   \fi%
 %    \end{macrocode}
-% Remeber points for display;
+% Remember points for display;
 % disable points display if desired:
 %    \begin{macrocode}
   \let\exf at subproblem@points at show\@undefined%
@@ -5793,19 +6170,18 @@
    \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:
+% Write points to |.aux| file; add to problem total:
 %    \begin{macrocode}
   \ifdefined\exf at subproblem@points%
    \global\let\exf at prevpoints\exf at subproblem@points%
+   \expandafter\exf at writesubproblempoints\exf at subproblem@points%
    \exf at exptwo\exf at addtopoints\exf at problem@points at total\exf at subproblem@points%
 %    \end{macrocode}
 % Warn if no points given for present subproblem but previously:
 %    \begin{macrocode}
-  \else%
-   \ifdefined\exf at problem@points at total%
-    \PackageWarning{exframe}{no points defined for \exf at subproblemname}%
-   \fi%
-  \fi%
+  \else\ifdefined\exf at problem@points at total%
+   \PackageWarning{exframe}{no points defined for \exf at subproblemname}%
+  \fi\fi%
 %    \end{macrocode}
 % Display points in opening line if desired;
 % expand points into argument and remove points:
@@ -5912,7 +6288,7 @@
 \define at key{exf at solution}{sheettag}{\def\sheettag{#1}}
 \define at key{exf at solution}{href}{\def\exf at solhref{#1}}
 \define at key{exf at solution}{label}{\def\exf at label{#1}}
-\define at key{exf at solution}{points}{\exf at scanpoints\exf at solution@points#1++&}
+\define at key{exf at solution}{points}{\exf at scanpoints\exf at solution@points#1++@}
 \define at key{exf at solution}{probtitle}{\def\exf at solprobtitle{#1}}
 %    \end{macrocode}
 
@@ -5963,7 +6339,7 @@
 %    \begin{macrocode}
   \ifdefined\exf at label\label{\exf at label}\fi%
 %    \end{macrocode}
-% Remeber points for display;
+% Remember points for display;
 % disable points display if desired:
 %    \begin{macrocode}
   \let\exf at solution@points at show\@undefined%
@@ -6399,6 +6775,184 @@
   {\exf at config@composetitlesolutionmulti}{\exf at solutionstitle}}
 %    \end{macrocode}
 
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Interaction with metastr}
+% \label{sec:imp-metastr}
+%
+% This package transfers some functionality
+% to the package \textsf{metastr} when loaded
+% previously (preferably with package option |course|)
+% by the package option |metastr|.
+% The following changes apply:
+% \begin{itemize}
+% \item
+% The terms specified by the configuration options |term...|,
+% see \secref{sec:imp-config},
+% are transferred to the corresponding term registers
+% |\metaterm{...}| in \textsf{metastr}.
+% This can facilitate internationalisation,
+% and suitable words for English, German, French and Spanish are provided.
+% \item
+% Metadata as described in \secref{sec:metadata}
+% should be filled via |\metaset| rather than |\exercisedata|.
+% The present package will read it from the \textsf{metastr} registers.
+% \item
+% Basic PDF metadata is written automatically or manually
+% as described in \secref{sec:metadata}.
+% This is done via |\metawritepdfinfo|,
+% consequently, automatic writing of these basic metadata
+% is disabled in \textsf{metastr}.
+% \item
+% Sheet-specific metadata (package option |pdfdata=sheet|)
+% is handled via the \textsf{metastr} registers |sheettitle| and |sheetdata|
+% rather than |composemetasheet|.
+% \end{itemize}
+%
+% Apply modifications only when package \textsf{metastr} is loaded:
+%    \begin{macrocode}
+\ifdefined\metaset
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Transfer Metadata.}
+%
+% Import basic data from \textsf{metastr}:
+%    \begin{macrocode}
+\exercisedata{author={\metapick[]{author}}}
+\exercisedata{title={\metapick[]{title}}}
+\exercisedata{subject={\metapick[]{subject}}}
+\exercisedata{keyword={\metapick[]{keyword}}}
+\exercisedata{date={\metapick[]{date}}}
+%    \end{macrocode}
+% Import course data from \textsf{metastr}:
+%    \begin{macrocode}
+\ifdefined\mstr at def@course
+\exercisedata{course={\metapick[]{course}}}
+\exercisedata{instructor={\metapick[]{instructor}}}
+\exercisedata{institution={\metapick[]{institution}}}
+\exercisedata{period={\metapick[]{period}}}
+\exercisedata{material={\metapick[]{material}}}
+\fi
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheet Data.}
+%
+% \macro{sheettitle}
+% \macro{sheetauthor}
+% Registers for sheet title and author:
+%    \begin{macrocode}
+\metadef{sheettitle}
+\metadef{sheetauthor}
+%    \end{macrocode}
+
+% \macro{\exf at writemetadata}
+% Write PDF metadata via \textsf{metastr} package,
+% let \textsf{exframe} initiate process (especially for sheet):
+%    \begin{macrocode}
+\metaunset[info]{writepdf}
+\def\exf at writemetadata{%
+  \exf at ifis\exf at metadata{sheet}{\metaset[use]{sheettitle}{}}%
+  \metawritepdfinfo%
+  \exf at ifis\exf at metadata{sheet}{\metaunset[use]{sheettitle}}}
+%    \end{macrocode}
+
+% Fill registers:
+%    \begin{macrocode}
+\metaset{sheetauthor}{\exerciseifempty{\getsheetdata{author}}%
+  {\metapick[#1]{instructor}}{\getsheetdata{author}}}
+\metaset{sheettitle}{\exerciseifempty{\getsheetdata{rawtitle}}%
+  {\metatranslate[#1]{sheet} \thesheet}%
+  {\getsheetdata{rawtitle}}}
+\metaset{author}{\exerciseifempty{\getsheetdata{author}}%
+  {\metapick[#1]{instructor}}{\metapick[#1]{sheetauthor}}}
+\metaset{subtitle}{%
+  \metaif[use]{sheettitle}
+   {\metapick[#1]{sheettitle}}
+   {\metapick[#1]{material}}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Terms.}
+%
+% \macro{term...}
+% Transfer term definitions to \textsf{metastr}:
+%    \begin{macrocode}
+\exerciseconfig{termsheet}{\metaterm{sheet}}
+\exerciseconfig{termsheets}{\metaterm{sheets}}
+\exerciseconfig{termproblem}{\metaterm{problem}}
+\exerciseconfig{termproblems}{\metaterm{problems}}
+\exerciseconfig{termsolution}{\metaterm{solution}}
+\exerciseconfig{termsolutions}{\metaterm{solutions}}
+\exerciseconfig{termpoint}{\metaterm{point}}
+\exerciseconfig{termpoints}{\metaterm{points}}
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Translations.}
+%
+% English:
+%    \begin{macrocode}
+\ifdefined\mstr at lang@en
+\metasetterm[en]{sheet}{Sheet}
+\metasetterm[en]{sheets}{Sheets}
+\metasetterm[en]{problem}{Problem}
+\metasetterm[en]{problems}{Problems}
+\metasetterm[en]{solution}{Solution}
+\metasetterm[en]{solutions}{Solutions}
+\metasetterm[en]{point}{point}
+\metasetterm[en]{points}{points}
+\fi
+%    \end{macrocode}
+
+% German:
+%    \begin{macrocode}
+\ifdefined\mstr at lang@de
+\metasetterm[de]{sheet}{Blatt}
+\metasetterm[de]{sheets}{Blätter}
+\metasetterm[de]{problem}{Aufgabe}
+\metasetterm[de]{problems}{Aufgaben}
+\metasetterm[de]{solution}{L\"osung}
+\metasetterm[de]{solutions}{L\"osungen}
+\metasetterm[de]{point}{Punkt}
+\metasetterm[de]{points}{Punkte}
+\fi
+%    \end{macrocode}
+
+% French:
+%    \begin{macrocode}
+\ifdefined\mstr at lang@fr
+\metasetterm[fr]{sheet}{Feuille}
+\metasetterm[fr]{sheets}{Feuilles}
+\metasetterm[fr]{problem}{Probl\`eme}
+\metasetterm[fr]{problems}{Probl\`emes}
+\metasetterm[fr]{solution}{Solution}
+\metasetterm[fr]{solutions}{Solutions}
+\metasetterm[fr]{point}{point}
+\metasetterm[fr]{points}{points}
+\fi
+%    \end{macrocode}
+
+% Spanish:
+%    \begin{macrocode}
+\ifdefined\mstr at lang@es
+\metasetterm[es]{sheet}{Hoja}
+\metasetterm[es]{sheets}{Hojas}
+\metasetterm[es]{problem}{Problema}
+\metasetterm[es]{problems}{Problemas}
+\metasetterm[es]{solution}{Solucion}
+\metasetterm[es]{solutions}{Soluciones}
+\metasetterm[es]{point}{punto}
+\metasetterm[es]{points}{puntos}
+\fi
+%    \end{macrocode}
+
+% Close \textsf{metastr} conditional:
+%    \begin{macrocode}
+\fi
+%    \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %\iffalse
 %</package>
 %\fi

Modified: trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty	2020-02-25 22:02:48 UTC (rev 53910)
+++ trunk/Master/texmf-dist/tex/latex/exframe/exframe.sty	2020-02-25 22:03:03 UTC (rev 53911)
@@ -17,7 +17,7 @@
 %% version 2005/12/01 or later.
 %% 
 \NeedsTeXFormat{LaTeX2e}[1996/12/01]
-\ProvidesPackage{exframe}[2020/01/11 v3.31 Framework for Exercise Problems]
+\ProvidesPackage{exframe}[2020/02/24 v3.4 Framework for Exercise Problems]
 
 \RequirePackage{verbatim}
 \RequirePackage{xkeyval}
@@ -31,6 +31,7 @@
 \long\def\exf at exparg#1#2{\exf at exptwo\exf at expswitch{#2}{#1}}
 \def\exf at csdo#1#2{\expandafter#1\csname#2\endcsname}
 \def\exf at csdotwo#1#2#3{\exf at exptwo#1#2\csname#3\endcsname}
+\def\exf at csor#1#2{\ifcsname#1\endcsname\csname#1\endcsname\else#2\fi}
 
 \long\def\exf at append@def#1#2{\exf at exptwo\def#1\expandafter{#1#2}}
 \long\def\exf at prepend@switch#1#2#3{#2{#3#1}}
@@ -52,6 +53,12 @@
 \newcommand{\exf at addcontentsline}[2]{%
   \ifx#1\exf at empty\else\addcontentsline{toc}{#1}{#2}\fi}
 
+\newcommand{\exf at notedata}[3]{\csname exf at notedata@#1\endcsname{#2}{#3}}
+\AtBeginDocument{\immediate\write\@auxout{%
+  \string\providecommand{\string\exf at notedata}[3]{}}}
+\newcommand{\exf at writedata}[3]%
+  {\immediate\write\@auxout{\string\exf at notedata{#1}{#2}{#3}}}
+
 \def\exf at problemname{problem}
 \def\exf at subproblemname{sub\exf at problemname}
 \def\exf at solutionname{solution}
@@ -72,6 +79,8 @@
 \define at boolkey{exframe.sty}[exf@]{extdata}[true]{}
 \define at boolkey{exframe.sty}[exf@]{extstyle}[true]{}
 
+\define at boolkey{exframe.sty}[exf@]{metastr}[true]{}
+
 \define at boolkey{exf at setup}[]{solutions}[true]{}
 \define at choicekey{exf at setup}{pdfdata}%
   {auto,manual,sheet,off}[auto]{\def\exf at metadata{#1}}
@@ -86,11 +95,18 @@
 \define at boolkey{exf at setup}[exf@]{solutionbuf}[true]{}
 \exf at solutionbuftrue
 \define at boolkey{exf at setup}[exf@]{problembuf}[true]{}
+\def\exf at emptytestchar{&}
+\define at key{exf at setup}{emptytestchar}{\def\exf at emptytestchar{#1}}
 
 \ProcessOptionsX<exframe.sty,exf at setup>
 
 \newcommand{\exercisesetup}[1]{\exf at expsetkeys{exf at setup}{#1}}
 
+\ifexf at metastr
+\PassOptionsToPackage{course=true}{metastr}
+\RequirePackage{metastr}
+\fi
+
 \newenvironment{onlysolutions}%
  {\ifsolutions\else%
    \let\endonlysolutions\endcomment%
@@ -111,8 +127,10 @@
 \newcommand{\exerciseconfigempty}[3]{\exf at csdo\ifx{exf at config@#1}\exf at empty%
   #2\else#3\fi}
 
-\long\def\exerciseifempty#1#2#3{\if&#1&#2\else#3\fi}
-\long\def\exerciseifnotempty#1#2{\if&#1&\else#2\fi}
+\long\def\exerciseifempty#1#2#3{%
+  \if\exf at emptytestchar#1\exf at emptytestchar#2\else#3\fi}
+\long\def\exerciseifnotempty#1#2{%
+  \if\exf at emptytestchar#1\exf at emptytestchar\else#2\fi}
 
 \exerciseconfig{termsheet}{Sheet}
 \exerciseconfig{termsheets}{Sheets}
@@ -302,8 +320,13 @@
 \exerciseconfig{counterproblemequation}{P\arabic{equation}}
 \exerciseconfig{countersolutionequation}{S\arabic{equation}}
 
+\exerciseconfig{tagsheet}{\arabic{\exf at sheetcounter}}
+\exerciseconfig{tagproblem}{\csname the\exf at problemcounter\endcsname}
+\exerciseconfig{tagsubproblem}{\problemtag-\arabic{\exf at subproblemcounter}}
+
 \exerciseconfig{labelsheet}[1]{sheet:#1}
 \exerciseconfig{labelproblem}[1]{prob:#1}
+\exerciseconfig{labelsubproblem}[1]{\getexerciseconfig{labelproblem}{#1}}
 
 \exerciseconfig{toclevelsheet}{}
 \exerciseconfig{toclevelproblem}{}
@@ -539,13 +562,13 @@
     \hypersetup{pdfsubject={\exf at data@subject}}\fi%
    \ifx\exf at data@keyword\exf at empty\else%
     \hypersetup{pdfkeywords={\exf at data@keyword}}\fi%
-  \fi%
-  \gdef\exf at metadata{off}}
+  \fi}
 
-\AtBeginDocument{\exf at ifis\exf at metadata{auto}{\exf at writemetadata}}
+\AtBeginDocument{\exf at ifis\exf at metadata{auto}%
+  {\exf at writemetadata\gdef\exf at metadata{off}}}
 
-\newcommand{\writeexercisedata}{%
-  \exf at ifis\exf at metadata{manual}{\exf at writemetadata}}
+\newcommand{\writeexercisedata}{\exf at ifis\exf at metadata{manual}%
+  {\exf at writemetadata\gdef\exf at metadata{off}}}
 
 \newcounter{\exf at sheetcounter}
 \newcounter{\exf at problemcounter}
@@ -569,7 +592,15 @@
 \newcommand{\exf at numberproblemwithin}[1]{%
   \@addtoreset{\exf at problemcounter}{#1}%
   \exf at csdo\def{the\exf at problemcounter}%
-   {\csname the#1\endcsname.\exf at config@counterproblem}}
+   {\csname the#1\endcsname.\exf at config@counterproblem}%
+  \edef\exf at tmp{#1}%
+  \ifx\exf at tmp\exf at sheetcounter%
+   \exerciseconfig{tagproblem}{\ifdefined\sheettag\sheettag-\fi%
+    \arabic{\exf at problemcounter}}%
+  \else%
+   \exerciseconfig{tagproblem}{\csname the#1\endcsname-%
+    \arabic{\exf at problemcounter}}%
+  \fi}
 
 \newcommand{\exf at numberequationwithin}[1]{%
   \@addtoreset{exf at sheetequation}{#1}%
@@ -702,9 +733,9 @@
    \global\let#3\@undefined\fi}
 \def\exf at outpoints@switch#1#2#3{#2{\protect#3#1}}
 
-\def\exf at scanpoints#1#2+#3+#4&{%
-  \edef#1{\if&#2&0\else#2\fi}%
-  \edef#1{{#1}{\if&#3&0\else#3\fi}}}
+\def\exf at scanpoints#1#2+#3+#4@{%
+  \edef#1{\if @#2 at 0\else#2\fi}%
+  \edef#1{{#1}{\if @#3 at 0\else#3\fi}}}
 \def\exf at formatpoints#1#2{\ifdim#2pt=0pt#1\else%
   \ifdim#1pt=0pt+#2\else#1+#2\fi\fi}
 
@@ -711,11 +742,11 @@
 \newcommand{\extractpoints}{\@ifstar{\exf at extractpoints\@secondoftwo}%
   {\exf at extractpoints\@firstoftwo}}
 \newcommand{\exf at extractpoints}[2]{\edef\exf at tmp{#2}%
-  \exf at exptwo\exf at scanpoints\exf at tmp\exf at tmp++&%
+  \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++&%
+  \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}%
@@ -752,8 +783,8 @@
   \edef\exf at tmp{#1}%
   \expandafter\exf at splitsign\exf at tmp--&%
   \expandafter\exf at splitdecimal\exf at splitnum..&%
-  \if&\exf at splitint&\def\exf at splitint{0}\fi%
-  \if&\exf at splitdec&\def\exf at splitdec{0}\fi%
+  \if @\exf at splitint @\def\exf at splitint{0}\fi%
+  \if @\exf at splitdec @\def\exf at splitdec{0}\fi%
   \def\exf at tmp{\exf at splitint.\exf at splitdec}%
   \ifnum\exf at splitdec=0\def\exf at tmp{\exf at splitint}\fi%
   \ifnum\exf at splitdec=5\def\exf at tmp{\exf at config@frac{\exf at splitint}{1}{2}}\fi%
@@ -767,41 +798,29 @@
 }
 
 \newcommand{\exf at config@frac}[3]{%
-  \ifnum#1=0\else#1\fi%
-  \ifnum#2=0\else$%
+  \ifnum#1=0\relax\else#1\fi%
+  \ifnum#2=0\relax\else$%
    ^{\exf at text{#2}}%
    \mskip-4mu/\mskip-2mu%
    _{\exf at text{#3}}$\fi}
 
-\newcommand{\exf at notesheetpoints}[2]{%
+\newcommand{\exf at notedata@sheetpoints}[2]{%
   \exf at csdo\gdef{exf at sheetpoints@#1}{#2}}
-\AtBeginDocument{\immediate\write\@auxout{%
-  \string\providecommand{\string\exf at notesheetpoints}[2]{}}}
 \newcommand{\exf at writesheetpoints}[2]%
-  {\immediate\write\@auxout{\string\exf at notesheetpoints{\sheettag}%
-   {\exf at formatpoints{#1}{#2}}}}
-\newcommand{\getsheetpoints}[1]{\if&#1&%
+  {\exf at writedata{sheetpoints}{\sheettag}{\exf at formatpoints{#1}{#2}}}
+\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}
+  \else\exf at csor{exf at sheetpoints@#1}{0}\fi}
 
-\newcommand{\exf at noteproblempoints}[2]{%
+\newcommand{\exf at notedata@problempoints}[2]{%
   \exf at csdo\gdef{exf at problempoints@#1}{#2}}
-\AtBeginDocument{\immediate\write\@auxout{%
-  \string\providecommand{\string\exf at noteproblempoints}[2]{}}}
 \newcommand{\exf at writeproblempoints}[2]%
-  {\immediate\write\@auxout{\string\exf at noteproblempoints{\problemtag}%
-   {\exf at formatpoints{#1}{#2}}}}
-\newcommand{\getproblempoints}[1]{\if&#1&%
+  {\exf at writedata{problempoints}{\problemtag}{\exf at formatpoints{#1}{#2}}}
+\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}
+  \else\exf at csor{exf at problempoints@#1}{0}\fi}
 
 \newcommand{\showpoints}{%
   \ifdefined\exf at in@solution\exf at outpoints{\exf at ensuretext}%
@@ -812,23 +831,80 @@
    {\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++&%
+\newcommand{\exf at notedata@subproblempoints}[2]{%
+  \exf at csdo\gdef{exf at subproblempoints@#1}{#2}}
+\newcommand{\exf at writesubproblempoints}[2]%
+  {\exf at writedata{subproblempoints}%
+   {\subproblemtag}{\exf at formatpoints{#1}{#2}}}
+\newcommand{\getsubproblempoints}[1]{\if @#1@%
+   \ifdefined\exf at subproblem@points%
+    \expandafter\exf at formatpoints\exf at subproblem@points\else 0\fi%
+  \else\exf at csor{exf at subproblempoints@#1}{0}\fi}
+
+\newcommand{\exf at awardpointsalt}[2][]{\exf at scanpoints\exf at tmp#2++@%
   \exf at exptwo\exf at ensuretext{%
    \expandafter\exf at config@composepointspairawardalt\exf at tmp{#1}}}
-\newcommand{\exf at awardpointsreg}[2][]{\exf at scanpoints\exf at tmp#2++&%
+\newcommand{\exf at awardpointsreg}[2][]{\exf at scanpoints\exf at tmp#2++@%
   \exf at exptwo\exf at addtopoints\exf at solution@points at total\exf at tmp%
-  \exf at scanpoints\exf at tmp#2++&%
+  \exf at scanpoints\exf at tmp#2++@%
   \exf at exptwo\exf at ensuretext{%
    \expandafter\exf at config@composepointspairaward\exf at tmp{#1}}}
 \newcommand{\awardpoints}{\@ifstar\exf at awardpointsalt\exf at awardpointsreg}
 
-\newcommand{\getsolutionpoints}[1]{\if&#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}}
+\newcounter{exerciseloop}
+\newcounter{exf at loopdepth}
+
+\def\exf at listwalk#1#2{\if @#2@\def\exf at tmp{}\else%
+  \def\exf at tmp{#1{#2}\exf at listwalk#1}\fi\exf at tmp}
+
+\newcommand{\exerciseloop}[2]{\addtocounter{exf at loopdepth}{1}%
+  \setcounter{exerciseloop}{0}%
+  \exf at csdo\gdef{exf at listcallback@\roman{exf at loopdepth}}##1%
+   {\stepcounter{exerciseloop}#2}%
+  \edef\exf at tmp{#1}%
+  \exf at csdotwo\exf at exptwo\exf at listwalk%
+   {exf at listcallback@\roman{exf at loopdepth}}\exf at tmp{}%
+  \addtocounter{exf at loopdepth}{-1}}
+\newcommand{\exerciseloopstr}[3][\exerciseloopret]{%
+  \def#1{}\exerciseloop{#2}{\protected at edef#1{#1#3}}}
+
+\def\exf at sheetlist{}
+\newcommand{\exf at notedata@sheet}[2]{%
+  \xdef\exf at sheetlist{\exf at sheetlist{#1}}}
+\def\exf at problemlist{}
+\newcommand{\exf at notedata@problem}[2]{%
+  \xdef\exf at problemlist{\exf at problemlist{#1}}%
+  \if @#2@\else%
+   \ifcsname exf at problemlist@#2\endcsname\else%
+    \exf at csdo\gdef{exf at problemlist@#2}{}\fi%
+   \exf at csdo\xdef{exf at problemlist@#2}%
+    {\csname exf at problemlist@#2\endcsname{#1}}%
+  \fi}
+\newcommand{\exf at notedata@subproblem}[2]{%
+  \ifcsname exf at subproblemlist@#2\endcsname\else%
+   \exf at csdo\gdef{exf at subproblemlist@#2}{}\fi%
+  \exf at csdo\xdef{exf at subproblemlist@#2}%
+   {\csname exf at subproblemlist@#2\endcsname{#1}}}
+
+\newcommand{\getsheetlist}[1]{\exf at sheetlist}
+\newcommand{\getproblemlist}[1]{\if @#1@%
+  \ifdefined\sheettag\exf at csor{exf at problemlist@\sheettag}{}%
+  \else\exf at problemlist\fi%
+ \else%
+  \if *#1\exf at problemlist\else\exf at csor{exf at problemlist@#1}{}\fi%
+ \fi}
+\newcommand{\getsubproblemlist}[1]{\if @#1@%
+  \exf at csor{exf at subproblemlist@\problemtag}{}\else%
+  \exf at csor{exf at subproblemlist@#1}{}\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}%
+  \addtocounter{\exf at sheetcounter}{-1}\refstepcounter{\exf at sheetcounter}}
 \define at key{exf at sheet}{label}{\def\exf at label{#1}}
 \define at key{exf at sheet}{tag}{\def\sheettag{#1}}
 
@@ -842,12 +918,13 @@
    \let\theHequation\theHexf at sheetequation%
   \fi%
   \let\exf at sheet@points\@undefined%
-  \def\sheettag{\csname the\exf at sheetcounter\endcsname}%
+  \def\sheettag{\getexerciseconfig{tagsheet}}%
   \let\exf at sheet@points at total\@undefined%
   \let\exf at label\@undefined%
   \setkeys{exf at sheet}{#1}%
   \ifexf at autolabelsheet\label{\exf at config@labelsheet{\sheettag}}\fi%
   \ifdefined\exf at label\label{\exf at label}\fi%
+  \exf at writedata{sheet}{\sheettag}{}%
   \ifdefined\exf at sheet@points%
    \let\exf at sheet@points at given\exf at empty%
   \else%
@@ -854,7 +931,7 @@
    \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++&%
+    \exf at exptwo\exf at scanpoints\exf at sheet@points\exf at tmp++@%
   \fi\fi%
   \exf at ifis\exf at metadata{sheet}{{%
    \ifx\exf at data@sheet at author\exf at empty\else%
@@ -861,7 +938,7 @@
     \let\exf at data@author\exf at data@sheet at author\fi%
    \def\exf at data@title{\exf at config@composemetasheet%
     {\csname the\exf at sheetcounter\endcsname}{\exf at data@sheet at rawtitle}}%
-   \exf at writemetadata}}%
+   \exf at writemetadata}\gdef\exf at metadata{off}}%
   \exf at config@insertsheetbefore%
   \ifx\exf at config@toclevelsheet\exf at empty\else%
    \ifdefined\phantomsection\phantomsection\fi\fi%
@@ -893,7 +970,7 @@
   \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 problem@points#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}}
@@ -911,7 +988,7 @@
    \let\theHequation\theHexf at problemequation%
   \fi%
   \exf at init@block{\exf at config@skipprobleminfo}%
-  \def\problemtag{\csname the\exf at problemcounter\endcsname}%
+  \def\problemtag{\getexerciseconfig{tagproblem}}%
   \let\exf at problem@points\@undefined%
   \let\exf at label\@undefined%
   \global\let\exf at sollabel\@undefined%
@@ -919,6 +996,7 @@
   \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%
+  \exf at writedata{problem}{\problemtag}{\ifdefined\sheettag\sheettag\fi}%
   \gdef\exf at problem@solnewsec{}%
   \xdef\exf at prevprob{\csname the\exf at problemcounter\endcsname}%
   \ifcsname theH\exf at problemcounter\endcsname%
@@ -938,7 +1016,7 @@
    \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++&%
+    \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%
@@ -996,8 +1074,7 @@
   \ifdefined\exf at problem@points%
    \expandafter\exf at writeproblempoints\exf at problem@points%
    \exf at exptwo\exf at addtopoints\exf at sheet@points at total\exf at problem@points%
-  \fi%
-  \ifdefined\exf at problem@points\else\ifdefined\exf at sheet@points at total%
+  \else\ifdefined\exf at sheet@points at total%
    \PackageWarning{exframe}{no points defined for \exf at problemname}%
   \fi\fi%
   \global\let\exf at prevsubprob\@undefined%
@@ -1102,8 +1179,9 @@
 
 \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}{points}{\exf at scanpoints\exf at subproblem@points#1++@}
 \define at key{exf at subproblem}{label}{\def\exf at label{#1}}
+\define at key{exf at subproblem}{tag}{\def\subproblemtag{#1}}
 
 \newenvironment{\exf at subproblemname}[1][]{%
   \par{\exf at config@styletext\addvspace{\exf at config@skipsubproblemabove}}%
@@ -1112,10 +1190,14 @@
   \begingroup%
   \def\exf at in@subproblem{}%
   \exf at init@block{\exf at config@skipsubprobleminfo}%
+  \def\subproblemtag{\getexerciseconfig{tagsubproblem}}%
   \let\exf at subproblem@points\@undefined%
   \let\exf at label\@undefined%
   \setkeys{exf at subproblem,exf at probleminfo}{#1}%
+  \ifexf at autolabelproblem\label{\exf at config@labelsubproblem%
+   {\subproblemtag}}\fi%
   \ifdefined\exf at label\label{\exf at label}\fi%
+  \exf at writedata{subproblem}{\subproblemtag}{\problemtag}%
   \xdef\exf at prevsubprob{\csname the\exf at subproblemcounter\endcsname}%
   \ifcsname theH\exf at subproblemcounter\endcsname%
    \xdef\exf at prevsubprobhref{\exf at subproblemcounter.%
@@ -1127,12 +1209,11 @@
   \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%
+   \expandafter\exf at writesubproblempoints\exf at subproblem@points%
    \exf at exptwo\exf at addtopoints\exf at problem@points at total\exf at subproblem@points%
-  \else%
-   \ifdefined\exf at problem@points at total%
-    \PackageWarning{exframe}{no points defined for \exf at subproblemname}%
-   \fi%
-  \fi%
+  \else\ifdefined\exf at problem@points at total%
+   \PackageWarning{exframe}{no points defined for \exf at subproblemname}%
+  \fi\fi%
   \exf at ifis\exf at subpointsat{start}{\exf at outpoints{\exf at append@intro}%
    {\exf at config@composepointspairstartsubproblem}{\exf at subproblem@points at show}}%
   \exf at ifis\exf at subpointsat{start*}{\exf at outpoints{\exf at prepend@intro}%
@@ -1181,7 +1262,7 @@
 \define at key{exf at solution}{sheettag}{\def\sheettag{#1}}
 \define at key{exf at solution}{href}{\def\exf at solhref{#1}}
 \define at key{exf at solution}{label}{\def\exf at label{#1}}
-\define at key{exf at solution}{points}{\exf at scanpoints\exf at solution@points#1++&}
+\define at key{exf at solution}{points}{\exf at scanpoints\exf at solution@points#1++@}
 \define at key{exf at solution}{probtitle}{\def\exf at solprobtitle{#1}}
 
 \newenvironment{printsolution}[1]{%
@@ -1438,6 +1519,97 @@
 \newcommand{\insertsolutions}{\exf at showsolutions%
   {\exf at config@composetitlesolutionmulti}{\exf at solutionstitle}}
 
+\ifdefined\metaset
+
+\exercisedata{author={\metapick[]{author}}}
+\exercisedata{title={\metapick[]{title}}}
+\exercisedata{subject={\metapick[]{subject}}}
+\exercisedata{keyword={\metapick[]{keyword}}}
+\exercisedata{date={\metapick[]{date}}}
+\ifdefined\mstr at def@course
+\exercisedata{course={\metapick[]{course}}}
+\exercisedata{instructor={\metapick[]{instructor}}}
+\exercisedata{institution={\metapick[]{institution}}}
+\exercisedata{period={\metapick[]{period}}}
+\exercisedata{material={\metapick[]{material}}}
+\fi
+
+\metadef{sheettitle}
+\metadef{sheetauthor}
+
+\metaunset[info]{writepdf}
+\def\exf at writemetadata{%
+  \exf at ifis\exf at metadata{sheet}{\metaset[use]{sheettitle}{}}%
+  \metawritepdfinfo%
+  \exf at ifis\exf at metadata{sheet}{\metaunset[use]{sheettitle}}}
+
+\metaset{sheetauthor}{\exerciseifempty{\getsheetdata{author}}%
+  {\metapick[#1]{instructor}}{\getsheetdata{author}}}
+\metaset{sheettitle}{\exerciseifempty{\getsheetdata{rawtitle}}%
+  {\metatranslate[#1]{sheet} \thesheet}%
+  {\getsheetdata{rawtitle}}}
+\metaset{author}{\exerciseifempty{\getsheetdata{author}}%
+  {\metapick[#1]{instructor}}{\metapick[#1]{sheetauthor}}}
+\metaset{subtitle}{%
+  \metaif[use]{sheettitle}
+   {\metapick[#1]{sheettitle}}
+   {\metapick[#1]{material}}}
+
+\exerciseconfig{termsheet}{\metaterm{sheet}}
+\exerciseconfig{termsheets}{\metaterm{sheets}}
+\exerciseconfig{termproblem}{\metaterm{problem}}
+\exerciseconfig{termproblems}{\metaterm{problems}}
+\exerciseconfig{termsolution}{\metaterm{solution}}
+\exerciseconfig{termsolutions}{\metaterm{solutions}}
+\exerciseconfig{termpoint}{\metaterm{point}}
+\exerciseconfig{termpoints}{\metaterm{points}}
+
+\ifdefined\mstr at lang@en
+\metasetterm[en]{sheet}{Sheet}
+\metasetterm[en]{sheets}{Sheets}
+\metasetterm[en]{problem}{Problem}
+\metasetterm[en]{problems}{Problems}
+\metasetterm[en]{solution}{Solution}
+\metasetterm[en]{solutions}{Solutions}
+\metasetterm[en]{point}{point}
+\metasetterm[en]{points}{points}
+\fi
+
+\ifdefined\mstr at lang@de
+\metasetterm[de]{sheet}{Blatt}
+\metasetterm[de]{sheets}{Blätter}
+\metasetterm[de]{problem}{Aufgabe}
+\metasetterm[de]{problems}{Aufgaben}
+\metasetterm[de]{solution}{L\"osung}
+\metasetterm[de]{solutions}{L\"osungen}
+\metasetterm[de]{point}{Punkt}
+\metasetterm[de]{points}{Punkte}
+\fi
+
+\ifdefined\mstr at lang@fr
+\metasetterm[fr]{sheet}{Feuille}
+\metasetterm[fr]{sheets}{Feuilles}
+\metasetterm[fr]{problem}{Probl\`eme}
+\metasetterm[fr]{problems}{Probl\`emes}
+\metasetterm[fr]{solution}{Solution}
+\metasetterm[fr]{solutions}{Solutions}
+\metasetterm[fr]{point}{point}
+\metasetterm[fr]{points}{points}
+\fi
+
+\ifdefined\mstr at lang@es
+\metasetterm[es]{sheet}{Hoja}
+\metasetterm[es]{sheets}{Hojas}
+\metasetterm[es]{problem}{Problema}
+\metasetterm[es]{problems}{Problemas}
+\metasetterm[es]{solution}{Solucion}
+\metasetterm[es]{solutions}{Soluciones}
+\metasetterm[es]{point}{punto}
+\metasetterm[es]{points}{puntos}
+\fi
+
+\fi
+
 \endinput
 %%
 %% End of file `exframe.sty'.



More information about the tex-live-commits mailing list.