summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/moodle
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2016-01-12 23:02:18 +0000
committerKarl Berry <karl@freefriends.org>2016-01-12 23:02:18 +0000
commit40e1a1e6a0ab09c8088183f91b4fe3752c207cd2 (patch)
tree83bc1a18dbe88c42382833162ac350b57ecc566b /Master/texmf-dist/tex/latex/moodle
parent29594b03973a1e16771ef0f22c06175799117bc7 (diff)
moodle (12jan16)
git-svn-id: svn://tug.org/texlive/trunk@39367 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/moodle')
-rw-r--r--Master/texmf-dist/tex/latex/moodle/moodle.sty2136
1 files changed, 2136 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/moodle/moodle.sty b/Master/texmf-dist/tex/latex/moodle/moodle.sty
new file mode 100644
index 00000000000..dedc78c95c9
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/moodle/moodle.sty
@@ -0,0 +1,2136 @@
+%%
+%% This is file `moodle.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% moodle.dtx (with options: `package')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2016 by Anders Hendrickson <anders.hendrickson@snc.edu>
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+\ProvidesPackage{moodle}
+ [2016/01/11 v0.5 Moodle quiz XML generation]
+\newif\ifmoodle@draftmode
+\newif\ifmoodle@tikzloaded
+
+%%DECLARATION OF OPTIONS
+\DeclareOption{draft}{\moodle@draftmodetrue}
+
+\moodle@draftmodefalse
+\moodle@tikzloadedfalse
+
+\ProcessOptions
+
+\RequirePackage{environ} %To be able to take environment body as a macro argument
+\RequirePackage{xkeyval} %For key-handling
+\RequirePackage{amssymb} %For \checkmark symbol
+\RequirePackage{trimspaces} %To remove extra spaces from strings
+\RequirePackage{etex} %Expansion control, detokenization, etc.
+\RequirePackage{etoolbox}%List management
+\RequirePackage{xpatch} %To patch commands easily in HTML mode
+\RequirePackage{array} %For formatting tables in the LaTeX mode of Clozes
+\RequirePackage{ifplatform} % To choose Ghostscript commands
+\RequirePackage{ifpdf} % Needed to know whether we can convert output from PDF to PNG
+
+\RequirePackage{getitems} %To gather the header and items
+
+\let\xa=\expandafter
+\def\@star{*}%
+\def\@hundred{100}%
+\def\@moodle@empty{}%
+\def\@relax{\relax}%
+\def\jobnamewithsuffixtomacro#1#2{%
+ \filenamewithsuffixtomacro{#1}{\jobname}{#2}%
+}
+\def\@jn@quote{"}%
+\def\filenamewithsuffixtomacro#1#2#3{%
+ % #1 = macro to create
+ % #2 = filename to add suffix to
+ % #3 = suffix to add
+ \edef\jn@suffix{#3}%
+ \def\jn@macro{#1}%
+ \xa\testforquote#2\@jn@rdelim
+}
+\def\testforquote#1#2\@jn@rdelim{%
+ \def\jn@test@i{#1}%
+ \ifx\jn@test@i\@jn@quote
+ % Involves quotes
+ \edef\jn@next{"\jn@stripquotes#1#2\jn@suffix"}%
+ \else
+ \edef\jn@next{#1#2\jn@suffix}%
+ \fi
+ \xa\xdef\jn@macro{\jn@next}%
+}
+\def\jn@stripquotes"#1"{#1}%
+
+\jobnamewithsuffixtomacro{\outputfilename}{-moodle.xml}
+\newwrite\moodle@outfile
+\def\openmoodleout{%
+ \immediate\openout\moodle@outfile=\outputfilename\relax
+ \writetomoodle{<?xml version="1.0" encoding="UTF-8"?>}%
+ \writetomoodle{<quiz>}%
+ \writetomoodle{ }%
+}%
+\def\closemoodleout{%
+ \writetomoodle{ }%
+ \writetomoodle{</quiz>}%
+ \immediate\closeout\moodle@outfile
+}%
+\def\calculateindent#1{%
+ \bgroup
+ \count0=\number#1\relax
+ \gdef\moodle@indent{}%
+ \calculateindent@int
+ \egroup
+}%
+\def\calculateindent@int{%
+ \ifnum\count0>0\relax
+ \g@addto@macro{\moodle@indent}{\otherspace}%
+ \advance\count0 by -1\relax
+ \expandafter
+ \calculateindent@int
+ \fi
+}%
+\newcommand\writetomoodle[2][0]{%
+ \edef\test@ii{#2}%
+ \ifnum#1=0\relax
+ \immediate\write\moodle@outfile{\test@ii}%
+ \else
+ \calculateindent{#1}%
+ \immediate\write\moodle@outfile{\moodle@indent\trim@pre@space{\test@ii}}%
+ \fi
+}%
+\newenvironment{quiz}[2][]%
+ {\setkeys{moodle}{#1}%
+ \@moodle@ifgeneratexml{%
+ \openmoodleout%
+ \setcategory{#2}%
+ }{}%
+ \subsection*{#2}%
+ \begin{enumerate}%
+ }
+ {\end{enumerate}%
+ \@moodle@ifgeneratexml{\closemoodleout}{}}
+
+{\catcode`\$=12\catcode`\ =12%
+\gdef\setcategory#1{%
+\writetomoodle{<question type="category">}%
+\writetomoodle{ <category>}%
+\writetomoodle{ <text>$module$/#1</text>}%
+\writetomoodle{ </category>}%
+\writetomoodle{</question>}%
+\writetomoodle{ }%
+}}%
+\def\passvalueaftergroup#1{%
+ \xa\xa\xa\gdef\xa\xa\csname moodle@remember@\string#1\endcsname\xa{\xa\def\xa#1\xa{#1}}%
+ \xa\aftergroup\csname moodle@remember@\string#1\endcsname
+}
+\long\def\@moodle@ifgeneratexml#1#2{%
+ % If we are generating XML, do #1; otherwise do #2.
+ \tikzifexternalizing{%
+ % This run of LaTeX is currently ONLY generating a Tikz image
+ % to be saved in an external file. We do NOT want to waste time
+ % generating XML, and moreover trying to do so would cause errors
+ % because of file dependencies.
+ #2%
+ }{%
+ \ifmoodle@draftmode
+ #2%
+ \else
+ #1%
+ \fi
+ }%
+}
+\def\moodleset#1{\setkeys{moodle}{#1}}%
+\def\generate@moodle@write@code{%
+ \@ifnextchar*\generate@moodle@write@data\generate@moodle@write@html
+}%
+
+\def\generate@moodle@write@html#1<#2>#3{%
+ % #1 = NAME for \moodle@writeNAME
+ % #2 = HTML tag
+ % #3 = what, exactly, to write
+ \xa\gdef\csname moodle@write#1\endcsname{%
+ \xa\def\xa\test@iii\xa{#3}%
+ \ifx\test@iii\@moodle@empty
+ \writetomoodle[2]{ <#2 format="html"><text/></#2>}%
+ \else
+ \xa\converttohtmlmacro\xa\moodle@htmltowrite\xa{#3}%
+ \writetomoodle[2]{ <#2 format="html">}%
+ \writetomoodle[4]{ <text><![CDATA[<p>\moodle@htmltowrite</p>]]></text>}%
+ \writetomoodle[2]{ </#2>}%
+ \fi
+ }%
+}%
+
+\def\generate@moodle@write@data*#1<#2>#3{%
+ % #1 = NAME for \moodle@writeNAME
+ % #2 = HTML tag
+ % #3 = what, exactly, to write
+ \xa\gdef\csname moodle@write#1\endcsname{%
+ \writetomoodle[2]{ <#2>#3</#2>}%
+ }%
+}%
+
+%% QUESTIONNAME
+ \define@cmdkey{moodle}[moodle@]{questionname}{}%
+ \gdef\moodle@writequestionname{%
+ \writetomoodle[2]{<name>}%
+ \writetomoodle[4]{ <text>\moodle@questionname</text>}%
+ \writetomoodle[2]{</name>}%
+ }%
+
+%% QUESTIONTEXT
+ %I tried to use questiontext as a key, but it doesn't seem to work.
+ %The trouble is that xkeyval has trouble parsing a key with a \par token followed by a comma within brackets,
+ %like \setkeys{moodle}{questiontext={ABC\par [D,E]}}
+ %It's not worth trying to fix.
+
+ \long\def\questiontext#1{%
+ %\converttohtmlmacro\myoutput{#1}%
+ %\let\moodle@questiontext=\myoutput%
+ \def\moodle@questiontext{#1}%
+ }%
+ \generate@moodle@write@code{questiontext}<questiontext>{\moodle@questiontext}%{%
+
+%% PENALTY FOR WRONG ATTEMPT
+ \define@cmdkey{moodle}[moodle@]{penalty}[0.1000000]{}%
+ \generate@moodle@write@code*{penalty}<penalty>{\moodle@penalty}%
+ \moodleset{penalty}%
+
+%% FEEDBACK
+ % Moodle allows for feedback tailored to each question,
+ % and feedback tailored to each right or wrong answer.
+ % We shall use the key 'feedback' to record both kinds of feedback,
+ % relying on TeX's grouping mechanism to keep them apart.
+ % When it comes time to write them to XML,
+ % \moodle@writegeneralfeedback uses the HTML tag <generalfeedback>
+ % whereas \moodle@writefeedback uses the tag <feedback>.
+ % Note that the general feedback is NOT inherited by each answer!
+ \define@cmdkey{moodle}[moodle@]{feedback}[]{}%
+ \generate@moodle@write@code{generalfeedback}<generalfeedback>{\moodle@feedback}%
+ \generate@moodle@write@code{feedback}<feedback>{\moodle@feedback}%
+ \moodleset{feedback}%
+
+%% DEFAULT GRADE
+ %The next line creates \moodle@defaultgrade,
+ %which is how many points the quiz question is worth.
+ %Key calls like [default grade=7] set \moodle@defaultgrade.
+ \define@cmdkey{moodle}[moodle@]{default grade}[1.0]{}%
+ %Next, makes 'points' a synonym for 'default grade'
+ \define@key{moodle}{points}[1.0]{\xa\def\csname moodle@default grade\endcsname{#1}}
+ \generate@moodle@write@code*{defaultgrade}<defaultgrade>{\csname moodle@default grade\endcsname}%
+ \moodleset{default grade=1.0} %This sets the default.
+
+%% HIDDEN
+ \define@boolkey{moodle}[moodle@]{hidden}[true]{}%
+ \generate@moodle@write@code*{hidden}<hidden>{\ifmoodle@hidden 1\else 0\fi}%
+ \moodleset{hidden=false}%
+
+\def\moodle@writecommondata{%
+ \moodle@writequestionname%
+ \moodle@writequestiontext%
+ \moodle@writedefaultgrade%
+ \moodle@writegeneralfeedback%
+ \moodle@writepenalty%
+ \moodle@writehidden%
+}%
+
+
+%% FRACTION -- how much this answer is worth out of 100 percent
+ \define@cmdkey{moodle}[moodle@]{fraction}[100]{}%
+ %We do not create \moodle@writefraction, because the fraction occurs in
+ %the XML within the answer tag, like <answer fraction="75">.
+ \moodleset{fraction=100} %This sets the default.
+
+%% SINGLE and MULTIPLE -- for multichoice, is there 1 right answer or more than 1?
+ \define@boolkey{moodle}[moodle@]{single}[true]{}%
+ \generate@moodle@write@code*{single}<single>{\ifmoodle@single true\else false\fi}%
+ \moodleset{single}%
+ %The key 'multiple' is an antonym to 'single'.
+ \define@boolkey{moodle}[moodle@]{multiple}[true]{\ifmoodle@multiple\moodle@singlefalse\else\moodle@singletrue\fi}%
+
+%% SHUFFLE ANSWERS
+ \define@boolkey{moodle}[moodle@]{shuffle}[true]{}%
+ \generate@moodle@write@code*{shuffle}<shuffleanswers>{\ifmoodle@shuffle 1\else 0\fi}%
+ \moodleset{shuffle=true}%
+
+%% TO DO: CORRECTFEEDBACK
+%% TO DO: PARTIALLYCORRECTFEEDBACK
+%% TO DO: INCORRECTFEEDBACK
+%% TO DO: NUMCORRECT key
+
+%% NUMBERING -- for numbering of multichoice questions
+ \define@choicekey{moodle}{numbering}%
+ {alpha,alph,Alpha,Alph,arabic,roman,Roman,%
+ abc,ABC,123,iii,IIII,none}[abc]{%
+ \def\moodle@numbering{#1}%
+ \def\test@@i{#1}%
+ \ifx\test@@i\@moodle@alpha
+ \def\moodle@numbering{abc}\fi
+ \ifx\test@@i\@moodle@alph
+ \def\moodle@numbering{abc}\fi
+ \ifx\test@@i\@moodle@Alpha
+ \def\moodle@numbering{ABC}\fi
+ \ifx\test@@i\@moodle@Alph
+ \def\moodle@numbering{ABC}\fi
+ \ifx\test@@i\@moodle@arabic
+ \def\moodle@numbering{123}\fi
+ \ifx\test@@i\@moodle@roman
+ \def\moodle@numbering{iii}\fi
+ \ifx\test@@i\@moodle@Roman
+ \def\moodle@numbering{IIII}\fi
+ }%
+ %'answer numbering' will be a synonym to 'numbering'
+ \define@key{moodle}{answer numbering}[abc]{\setkeys{moodle}{numbering={#1}}}%
+ \generate@moodle@write@code*{answernumbering}<answernumbering>{\moodle@numbering}%
+ %N.B. if we did not set the default here, then \moodle@numbering would be undefined, causing problems.
+ \moodleset{answer numbering=abc}%
+
+ \def\@moodle@alpha{alpha}%
+ \def\@moodle@Alpha{Alpha}%
+ \def\@moodle@alph{alph}%
+ \def\@moodle@Alph{Alph}%
+ \def\@moodle@arabic{arabic}%
+ \def\@moodle@roman{roman}%
+ \def\@moodle@Roman{Roman}%
+ \def\@moodle@abc{abc}%
+ \def\@moodle@ABC{ABC}%
+ \def\@moodle@arabicnumbers{123}%
+ \def\@moodle@iii{iii}%
+ \def\@moodle@IIII{IIII}%
+ \def\@moodle@none{none}%
+ \def\moodle@obeynumberingstyle{%
+ \ifx\moodle@numbering\@moodle@abc
+ \renewcommand\theenumii{\alph{enumii}}%
+ \fi
+ \ifx\moodle@numbering\@moodle@ABC
+ \renewcommand\theenumii{\Alph{enumii}}%
+ \fi
+ \ifx\moodle@numbering\@moodle@arabicnumbers
+ \renewcommand\theenumii{\arabic{enumii}}%
+ \fi
+ \ifx\moodle@numbering\@moodle@iii
+ \renewcommand\theenumii{\roman{enumii}}%
+ \fi
+ \ifx\moodle@numbering\@moodle@IIII
+ \renewcommand\theenumii{\Roman{enumii}}%
+ \fi
+ \ifx\moodle@numbering\@moodle@none
+ \renewcommand\labelenumii{$\bullet$~}%
+ \fi
+ }
+ %TO DO: * In the PDF, how should 'none' in a multi look different from
+ % short answer or numerical options?
+ % * Instead of \theenumi and \labelenumi,
+ % use \@enumdepth to automatically set the correct depth.
+
+%% DISPLAY MODE -- affects Cloze multiple choice questions only.
+ % 0 = inline, 1 = vertical, 2 = horizontal
+ \def\moodle@multi@mode{0}%
+ \define@key{moodle}{inline}[]{\def\moodle@multi@mode{0}}%
+ \define@key{moodle}{vertical}[]{\def\moodle@multi@mode{1}}%
+ \define@key{moodle}{horizontal}[]{\def\moodle@multi@mode{2}}%
+%% TOLERANCE
+ \define@cmdkey{moodle}[moodle@]{tolerance}[0]{}%
+ \moodleset{tolerance=0}%
+ %There is no \moodle@writetolerance, because in the XML the
+ %tolerance is given within the answer tag,
+ %like <answer fraction=100 tolerance=0.03>.
+
+%% CASE SENSITIVE
+ \define@boolkey{moodle}[moodle@]{case sensitive}[true]{}%
+ \generate@moodle@write@code*{usecase}<usecase>{\csname ifmoodle@case sensitive\endcsname 1\else 0\fi}%
+ % We make 'usecase' a synonym for 'case sensitive'.
+ \define@boolkey{moodle}[moodle@]{usecase}[true]{\ifmoodle@usecase\csname moodle@case sensitivetrue\endcsname\else\csname moodle@case sensitivefalse\endcsname\fi}%
+ \moodleset{case sensitive=false}%
+%% DRAG-AND-DROP FORMAT
+ \define@boolkey{moodle}[moodle@]{draganddrop}[true]{}%
+ % We make 'dd' and 'dragdrop' and 'drag and drop' synonyms for 'draganddrop'.
+ \define@boolkey{moodle}[moodle@]{dd}[true]{\ifmoodle@dd\moodle@draganddroptrue\else\moodle@draganddropfalse\fi}%
+ \define@boolkey{moodle}[moodle@]{drag and drop}[true]{\moodle@ddsynonym}%
+ \def\moodle@ddsynonym{%
+ \csname ifmoodle@drag and drop\endcsname
+ \moodle@draganddroptrue
+ \else
+ \moodle@draganddropfalse
+ \fi
+ }
+ \moodleset{draganddrop=false}%
+%% EDITOR
+ \def\@moodle@html{html}%
+ \def\@moodle@htmlfile{html+file}%
+ \def\@moodle@text{text}%
+ \def\@moodle@plain{plain}%
+ \def\@moodle@monospaced{monospaced}%
+ \def\@moodle@file{file}%
+ \def\@moodle@noinline{noinline}%
+ \define@choicekey{moodle}{response format}%
+ {html,html+file,text,monospaced,file}[html]%
+ {\def\test@i{#1}%
+ \ifx\test@i\@moodle@html
+ % HTML Editor
+ \def\moodle@responseformat{editor}%
+ \fi
+ \ifx\test@i\@moodle@htmlfile
+ % HTML Editor with File Picker
+ \def\moodle@responseformat{editorfilepicker}%
+ \fi
+ \ifx\test@i\@moodle@text
+ % Plain text
+ \def\moodle@responseformat{plain}%
+ \fi
+ \ifx\test@i\@moodle@plain
+ % Plain text
+ \def\moodle@responseformat{plain}%
+ \fi
+ \ifx\test@i\@moodle@monospaced
+ % Plain text, monospaced font
+ \def\moodle@responseformat{monospaced}%
+ \fi
+ \ifx\test@i\@moodle@file
+ % No inline text (i.e., attachments only)
+ \def\moodle@responseformat{noinline}%
+ \fi
+ \ifx\test@i\@moodle@noinline
+ % No inline text (i.e., attachments only)
+ \def\moodle@responseformat{noinline}%
+ \fi
+ }%
+ \generate@moodle@write@code*{responseformat}<responseformat>{\moodle@responseformat}%
+ \moodleset{response format=html}%
+ %N.B. if we did not set a default, then \moodle@responseformat would be undefined, causing problems.
+
+%% RESPONSE REQUIRED
+ \define@boolkey{moodle}[moodle@]{response required}[true]{}%
+ % TO DO: Make synonym 'required'
+ \generate@moodle@write@code*{responserequired}<responserequired>{\csname ifmoodle@response required\endcsname 1\else 0\fi}%
+ \moodleset{response required=false}%
+
+%% RESPONSEFIELDLINES
+ \define@cmdkey{moodle}[moodle@]{response field lines}[15]{}%
+ \generate@moodle@write@code*{responsefieldlines}<responsefieldlines>{\csname moodle@response field lines\endcsname}%
+ %Make synonyms 'input box size' or 'height' or 'lines'?
+ \moodleset{response field lines=15}% N.B. if we do not set a default, then \moodle@responseformat will be undefined, causing problems.
+
+%% ATTACHMENTS ALLOWED
+ \def\@moodle@unlimited{unlimited}%
+ \define@choicekey{moodle}{attachments allowed}{0,1,2,3,unlimited}[1]{%
+ \def\test@i{#1}%
+ \ifx\test@i\@moodle@unlimited
+ \def\moodle@attachmentsallowed{-1}%
+ \else
+ \def\moodle@attachmentsallowed{#1}%
+ \fi
+ }
+ \generate@moodle@write@code*{attachmentsallowed}<attachments>{\moodle@attachmentsallowed}
+ \moodleset{attachments allowed=0}%
+
+%% ATTACHMENTS REQUIRED
+ \define@choicekey{moodle}{attachments required}{0,1,2,3}[1]{\def\moodle@attachmentsrequired{#1}}%
+ \generate@moodle@write@code*{attachmentsrequired}<attachmentsrequired>{\moodle@attachmentsrequired}
+ \moodleset{attachments required=0}%
+
+%% RESPONSE TEMPLATE
+ \define@key{moodle}{template}{\long\def\moodle@responsetemplate{#1}}%
+ \generate@moodle@write@code{responsetemplate}<responsetemplate>{\moodle@responsetemplate}
+ \moodleset{template={}}%
+%% SHOWNUMCORRECT
+ \define@boolkey{moodle}[moodle@]{shownumcorrect}[true]{}%
+ \gdef\moodle@writeshownumcorrect{%
+ \if\moodle@shownumcorrect
+ \writetomoodle[4]{ <shownumcorrect/>}%
+ \fi
+ }%
+ \moodleset{shownumcorrect=false}%
+
+%% CLEARWRONG
+ \define@boolkey{moodle}[moodle@]{clearwrong}[true]{}%
+ \gdef\moodle@writeclearwrong{%
+ \if\moodle@clearwrong
+ \writetomoodle[4]{ <clearwrong/>}%
+ \fi
+ }%
+ \moodleset{clearwrong=false}%
+
+
+\def\moodle@answers@xml{}%
+\gdef\moodle@writeanswers{%
+ \writetomoodle{\moodle@answers@xml}%
+}%
+
+\newcommand\addto@xml[3][0]{%
+ % #1 = spaces to indent (default=0)
+ % #2 = macro containing XML code (possibly empty)
+ % #3 = XML text to be appended to that macro (will be \edef'd)
+ \calculateindent{#1}%
+ \edef\xml@to@add{\moodle@indent\trim@pre@space{#3}}%
+ \ifx#2\@moodle@empty
+ \edef\newxml{\noexpand#2\xml@to@add}%
+ \else
+ \edef\newxml{\noexpand#2^^J\xml@to@add}%
+ \fi
+ \xa\xa\xa\def\xa\xa\xa#2\xa\xa\xa{\newxml}%
+}%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TRUE/FALSE QUESTIONS %%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% DESCRIPTION 'QUESTIONS' %%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% CALCULATED %%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+\def\moodle@makefrontend#1{%
+ \NewEnviron{#1}[2][]{%
+ \bgroup
+ \setkeys{moodle}{##1,questionname={##2}}%
+ \expandafter\gatheritems\xa{\BODY}%
+ \let\moodle@questionheader=\gatheredheader
+ %First, the LaTeX processing
+ \item \textbf{\moodle@questionname}\par
+ \noindent
+ \moodle@questionheader
+ \csname moodle@#1@latexprocessing\endcsname
+ %Now, writing information to XML
+ \@moodle@ifgeneratexml{%
+ \xa\questiontext\xa{\moodle@questionheader}% Save the question text.
+ \bgroup
+ \gdef\moodle@answers@xml{}%
+ \setkeys{moodle}{feedback={}}%
+ \xa\loopthroughitemswithcommand\xa{\csname save#1answer\endcsname}%
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+ \csname write#1question\endcsname
+ }{}%
+ \egroup
+ }%
+}
+\def\moodle@essay@latexprocessing{%
+ % Moodle cannot automatically grade an essay,
+ % but if the user puts \item's in, we can list them in an itemize as notes.
+ \ifnum\c@numgathereditems>0\relax
+ \par\noindent Notes: (not included in XML)
+ \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@essay@answer}%
+ \end{itemize}%
+ \fi
+}
+
+\NewEnviron{essay}[2][]{%
+ \bgroup
+ \setkeys{moodle}{#1,questionname={#2}}%
+ \expandafter\gatheritems\expandafter{\BODY}%
+ \let\moodle@questionheader=\gatheredheader
+ %First, the LaTeX processing.
+ \item \textbf{\moodle@questionname}\par
+ \noindent
+ \moodle@questionheader
+ \csname moodle@essay@latexprocessing\endcsname
+ %Now, writing information to memory.
+ \@moodle@ifgeneratexml{%
+ \xa\questiontext\xa{\moodle@questionheader}% Save the question text.
+ \bgroup
+ \gdef\moodle@answers@xml{}%
+ %
+ \ifnum\c@numgathereditems=0\relax
+ \addto@xml[2]\moodle@answers@xml{<graderinfo format="html"><text/></graderinfo>}%
+ \else
+ \addto@xml[2]\moodle@answers@xml{<graderinfo format="html"><text><![CDATA[}%
+ \ifnum\c@numgathereditems>1\relax
+ \addto@xml[4]\moodle@answers@xml{<ul>}%
+ \fi
+ \loopthroughitemswithcommand{\moodle@savegraderinfo}%
+ \ifnum\c@numgathereditems>1\relax
+ \addto@xml[4]\moodle@answers@xml{</ul>}%
+ \fi
+ \addto@xml[2]\moodle@answers@xml{]]></text></graderinfo>}%
+ \fi
+ %
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+ \writeessayquestion
+ }{}%
+ \egroup
+}%
+
+%%%% TO DO
+%%%% To make essay work will be tough.
+%%%% Every line from \ifnum\c@numgathereditems=0\relax through its \else and \fi,
+%%%% with the exception of
+%%%% \xa\loopthroughitemswithcommand\xa{\csname save#1answer\endcsname}%
+%%%% , does not exist in our current \moodle@makefrontend code.
+%%%% How can we cope?
+%%%%
+%%%% Idea: change \moodle@makefrontend so that
+%%%% 1. if \c@numgathereditems=0, we don't do anything.
+%%%% 2. it calls a preamble and postamble around the \loopthroughitemswithcommand.
+%%%% Like this:
+%%%%
+%%%% \@moodle@ifgeneratexml{%
+%%%% \xa\questiontext\xa{\moodle@questionheader}% Save the question text.
+%%%% \bgroup
+%%%% \gdef\moodle@answers@xml{}%
+%%%% \setkeys{moodle}{feedback={}}%
+%%%% \@ifundefined{moodle@#1@answers@preamble}{}{}%
+%%%% \csname moodle@#1@answers@preamble\endcsname
+%%%% \ifnum\c@numgathereditems=0\relax
+%%%% \relax
+%%%% \else
+%%%% \xa\loopthroughitemswithcommand\xa{\csname save#1answer\endcsname}%
+%%%% \fi
+%%%% \@ifundefined{moodle@#1@answers@postamble}{}{}%
+%%%% \csname moodle@#1@answers@postamble\endcsname
+%%%% \passvalueaftergroup{\moodle@answers@xml}%
+%%%% \egroup
+%%%% \csname write#1question\endcsname
+%%%% }{}%
+%%%% The \@ifundefined lines should automatically define the
+%%%% \...@preamble \...@postamble macros to be \relax if they don't exist already.
+
+\gdef\writeessayquestion{%
+ \writetomoodle{<question type="essay">}%
+ \moodle@writecommondata%
+ \moodle@writeresponserequired%
+ \moodle@writeresponseformat%
+ \moodle@writeresponsefieldlines%
+ \moodle@writeattachmentsallowed%
+ \moodle@writeattachmentsrequired%
+ \moodle@writeanswers% The 'answers' XML really contains the grader info.
+ \moodle@writeresponsetemplate%
+ \writetomoodle{</question>}%
+}%
+
+\def\moodle@print@essay@answer#1{%
+ \item #1%
+}%
+
+\def\moodle@savegraderinfo#1{%
+ \bgroup
+ \moodle@savegraderinfo@int#1\moodle@answer@rdelim
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+}%
+\newcommand\moodle@savegraderinfo@int[1][]{%
+ \setkeys{moodle}{fraction=0,#1}%
+ \moodle@savegraderinfo@int@int%
+}%
+\def\moodle@savegraderinfo@int@int#1\moodle@answer@rdelim{%
+ \xa\converttohtmlmacro\xa\moodle@answertext@html\xa{#1}%
+ %\trim@spaces@in\moodle@answertext
+ \ifnum\c@numgathereditems>1\relax
+ \addto@xml[6]{\moodle@answers@xml}{<li>\moodle@answertext@html</li>}%
+ \else
+ \addto@xml[4]{\moodle@answers@xml}{\moodle@answertext@html}%
+ \fi
+}%
+\def\blank{\rule{1in}{0.5pt}}%
+
+
+\moodle@makefrontend{shortanswer}%
+
+\def\moodle@shortanswer@latexprocessing{%
+ \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@shortanswer@answer}%
+ \end{itemize}%
+}
+
+ \def\moodle@print@shortanswer@answer#1{%
+ \moodle@print@shortanswer@answer@int#1\@rdelim
+ }%
+ \newcommand\moodle@print@shortanswer@answer@int[1][]{%
+ \setkeys{moodle}{#1}%
+ \moodle@print@shortanswer@answer@int@int%
+ }%
+ \def\moodle@print@shortanswer@answer@int@int#1\@rdelim{%
+ \ifx\moodle@fraction\@hundred
+ \item #1\quad$\checkmark$%
+ \else
+ \item #1\quad (\moodle@fraction\%)%
+ \fi
+ }%
+
+\def\saveshortansweranswer#1{%
+ \bgroup
+ \saveshortansweranswer@int#1\moodle@answer@rdelim
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+}%
+ \newcommand\saveshortansweranswer@int[1][]{%
+ \setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
+ \saveshortansweranswer@int@int%
+ }%
+ \def\saveshortansweranswer@int@int#1\moodle@answer@rdelim{%
+ \def\moodle@answertext{#1}%
+ \addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="plain_text">}%
+ \addto@xml[4]{\moodle@answers@xml}{ <text>\moodle@answertext</text>}%
+ \ifx\moodle@feedback\@empty\relax\else
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
+ \fi
+ \addto@xml[2]{\moodle@answers@xml}{</answer>}%
+ }%
+
+\gdef\writeshortanswerquestion{%
+ \writetomoodle{<question type="shortanswer">}%
+ \moodle@writecommondata%
+ \moodle@writeusecase%
+ \moodle@writeanswers%
+ \writetomoodle{</question>}%
+}%
+\moodle@makefrontend{numerical}%
+
+\def\moodle@numerical@latexprocessing{%
+ \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@numerical@answer}%
+ \end{itemize}%
+}
+
+ \def\moodle@print@numerical@answer#1{%
+ \moodle@print@numerical@answer@int#1\@rdelim
+ }%
+ \newcommand\moodle@print@numerical@answer@int[1][]{%
+ \setkeys{moodle}{#1}%
+ \moodle@print@numerical@answer@int@int%
+ }%
+ \def\moodle@print@numerical@answer@int@int#1\@rdelim{%
+ \ifdim0pt=\moodle@tolerance pt\relax
+ \def\moodle@numericalprint@tolerance{}%
+ \else
+ \edef\moodle@numericalprint@tolerance{\noexpand\pm\moodle@tolerance}%
+ \fi
+ \ifx\moodle@fraction\@hundred
+ \item $#1\moodle@numericalprint@tolerance\quad\checkmark$%
+ \else
+ \item $#1\moodle@numericalprint@tolerance$\quad (\moodle@fraction\%)%
+ \fi
+ }%
+
+\def\savenumericalanswer#1{%
+ \bgroup
+ \savenumericalanswer@int#1\moodle@answer@rdelim
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+}%
+ \newcommand\savenumericalanswer@int[1][]{%
+ \setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
+ \savenumericalanswer@int@int%
+ }%
+ \def\savenumericalanswer@int@int#1\moodle@answer@rdelim{%
+ \def\moodle@answertext{#1}%
+ \addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="plain_text">}%
+ \addto@xml[4]{\moodle@answers@xml}{ <text>\moodle@answertext</text>}%
+ \addto@xml[4]{\moodle@answers@xml}{ <tolerance>\moodle@tolerance</tolerance>}%
+ \ifx\moodle@feedback\@empty\relax\else
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
+ \fi
+ \addto@xml[2]{\moodle@answers@xml}{</answer>}%
+ }%
+
+\gdef\writenumericalquestion{%
+ \writetomoodle{<question type="numerical">}%
+ \moodle@writecommondata%
+ \moodle@writeanswers%
+ \writetomoodle{</question>}%
+}%
+
+\moodle@makefrontend{multi}
+
+\def\moodle@multi@latexprocessing{%
+ \moodle@countcorrectanswers
+ \begin{enumerate}\moodle@obeynumberingstyle
+ %\renewcommand{\theenumi}{\alph{enumi}}%
+ \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@multichoice@answer}%
+ \end{enumerate}%
+}
+ \def\moodle@print@multichoice@answer#1{%
+ \moodle@print@multichoice@answer@int#1\@rdelim
+ }%
+ \newcommand\moodle@print@multichoice@answer@int[1][]{%
+ \setkeys{moodle}{fraction=0,#1}%
+ \moodle@print@multichoice@answer@int@int
+ }%
+ \def\moodle@print@multichoice@answer@int@int#1#2\@rdelim{%
+ \def\test@i{#1}%
+ \ifmoodle@single
+ \ifx\test@i\@star
+ \item #2$~\checkmark$%
+ \else
+ \item #1#2%
+ \fi
+ \else
+ \ifx\test@i\@star
+ \item #2%
+ \setkeys{moodle}{fraction=\moodle@autopoints}%
+ \else
+ \item #1#2%
+ \fi
+ $~(\moodle@fraction\%)$
+ \fi
+ }%
+
+ \newcounter{moodle@numcorrectanswers}%
+ \newlength{\moodle@pointspercorrect}%
+ \def\moodle@countcorrectanswers{%
+ \setcounter{moodle@numcorrectanswers}{0}%
+ \global\setlength{\moodle@pointspercorrect}{100pt}%
+ \loopthroughitemswithcommand{\moodle@countcorrectanswers@a}%
+ \ifnum0=\c@moodle@numcorrectanswers\relax
+ \PackageError{moodle}{No correct answers given for multiple choice question.}{Please mark at least one answer correct.}%
+ \gdef\moodle@autopoints{0}%
+ \else
+ \global\divide\moodle@pointspercorrect by \c@moodle@numcorrectanswers\relax
+ \edef\moodle@autopoints{\strip@pt\moodle@pointspercorrect}%
+ \fi
+ }
+ \def\moodle@countcorrectanswers@a#1{%
+ %The grouping is to keep key answer-specific key changes local.
+ \bgroup
+ \moodle@countcorrectanswers@b#1\moodle@answer@rdelim
+ \egroup
+ }%
+ \newcommand\moodle@countcorrectanswers@b[1][]{%
+ \setkeys{moodle}{fraction=0,#1}%
+ \moodle@countcorrectanswers@c%
+ }%
+ \def\moodle@countcorrectanswers@c#1#2\moodle@answer@rdelim{%
+ \def\test@i{#1}%
+ \ifx\test@i\@star
+ \stepcounter{moodle@numcorrectanswers}%
+ \else
+ \global\addtolength{\moodle@pointspercorrect}{-\moodle@fraction pt}%
+ \fi
+ }%
+ \def\moodle@setautopoints#1pt{%
+ \gdef\moodle@autopoints{#1}%
+ }
+
+
+\def\savemultianswer#1{%
+ \bgroup
+ \savemultianswer@int#1\moodle@answer@rdelim
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+}%
+ \newcommand\savemultianswer@int[1][]{%
+ \setkeys{moodle}{fraction=0,#1}%
+ \savemultianswer@int@int%
+ }%
+ \def\savemultianswer@int@int#1#2\moodle@answer@rdelim{%
+ \def\test@i{#1}%
+ \ifx\test@i\@star
+ \ifmoodle@single
+ \setkeys{moodle}{fraction=100}%
+ \else
+ \setkeys{moodle}{fraction=\moodle@autopoints}%
+ \fi
+ \def\moodle@answertext{#2}%
+ \else
+ \def\moodle@answertext{#1#2}%
+ \fi
+ \trim@spaces@in\moodle@answertext
+ \addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="html">}%
+ \xa\converttohtmlmacro\xa\moodle@answertext@html\xa{\moodle@answertext}%
+ \addto@xml[4]{\moodle@answers@xml}{ <text><![CDATA[<p>\moodle@answertext@html</p>]]></text>}%
+ \ifx\moodle@feedback\@empty\relax\else
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
+ \fi
+ \addto@xml[2]{\moodle@answers@xml}{</answer>}%
+ }%
+
+\gdef\writemultiquestion{%
+ \writetomoodle{<question type="multichoice">}%
+ \moodle@writecommondata%
+ \moodle@writesingle%
+ \moodle@writeshuffle%
+ \moodle@writeanswernumbering%
+ \moodle@writeanswers%
+ \writetomoodle{</question>}%
+}%
+\let\answer=\hfill
+
+\moodle@makefrontend{matching}
+
+\def\moodle@matching@latexprocessing{%
+ \bgroup
+ \let\answer=\hfill
+ \begin{enumerate}\renewcommand{\theenumi}{\alph{enumi}}\setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@matching@answer}%
+ \end{enumerate}%
+ \egroup
+}
+ \long\def\moodle@print@matching@answer#1{%
+ \moodle@print@matching@answer@int#1\@rdelim
+ }%
+ \newcommand\moodle@print@matching@answer@int[1][]{%
+ \moodle@print@matching@answer@int@int\relax
+ }%
+ \long\def\moodle@print@matching@answer@int@int#1\answer#2\@rdelim{%
+ \item #1\hfill #2%
+ }%
+
+\long\def\savematchinganswer#1{%
+ \bgroup
+ \savematchinganswer@int#1\moodle@answer@rdelim%
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+}%
+ \newcommand\savematchinganswer@int[1][]{%
+ \setkeys{moodle}{#1}%
+ \xa\savematchinganswer@int@int\space%
+ }%
+ \long\def\savematchinganswer@int@int#1\answer#2\moodle@answer@rdelim{%
+ % Note that #1 may simply be \relax.
+ \def\moodle@subquestiontext{#1}%
+ \def\moodle@subanswertext{#2}%
+ \trim@spaces@in\moodle@subquestiontext
+ \xa\converttohtmlmacro\xa\moodle@subquestiontext@htmlized\xa{\moodle@subquestiontext}%
+ \trim@spaces@in\moodle@subanswertext
+ \ifmoodle@draganddrop
+ \xa\converttohtmlmacro\xa\moodle@subanswertext@htmlized\xa{\moodle@subanswertext}%
+ \fi
+ \addto@xml[2]{\moodle@answers@xml}{<subquestion format="html">}%
+ \ifx\moodle@subquestiontext\@empty
+ \addto@xml[4]{\moodle@answers@xml}{ <text></text>}%
+ \else
+ \addto@xml[4]{\moodle@answers@xml}{ <text><![CDATA[<p>\moodle@subquestiontext@htmlized</p>]]></text>}%
+ \fi
+ \ifmoodle@draganddrop
+ \addto@xml[4]{\moodle@answers@xml}{ <answer format="html"><text><![CDATA[<p>\moodle@subanswertext@htmlized</p>]]></text></answer>}%
+ \else
+ \addto@xml[4]{\moodle@answers@xml}{ <answer><text>\moodle@subanswertext</text></answer>}%
+ \fi
+ \ifx\moodle@feedback\@empty\relax\else
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
+ \fi
+ \addto@xml[2]{\moodle@answers@xml}{</subquestion>}%
+ }%
+
+\gdef\writematchingquestion{%
+ \ifmoodle@draganddrop
+ \writetomoodle{<question type="ddmatch">}%
+ \else
+ \writetomoodle{<question type="matching">}%
+ \fi
+ \moodle@writecommondata%
+ \moodle@writesingle%
+ \moodle@writeshuffle%
+ \moodle@writeanswernumbering%
+ \moodle@writeanswers%
+ \writetomoodle{</question>}%
+}%
+
+\NewEnviron{cloze}[2][]{%
+ \bgroup
+ \setkeys{moodle}{default grade=1}%
+ \setkeys{moodle}{#1,questionname={#2}}%
+ % A cloze question won't have any \item's in it, so we just use \BODY.
+ \moodle@enableclozeenvironments
+ %First, the LaTeX processing.
+ \item \textbf{\moodle@questionname}\par
+ \noindent
+ \BODY
+ %Now, writing information to memory.
+ \@moodle@ifgeneratexml{%
+ \xa\questiontext\xa{\BODY}% Save the question text as HTML.
+ \writeclozequestion
+ }{}%
+ \egroup%
+}
+
+\def\moodle@enableclozeenvironments{%
+ \let\multi=\clozemulti
+ \let\endmulti=\endclozemulti
+ \let\numerical=\clozenumerical
+ \let\endnumerical=\endclozenumerical
+ \let\shortanswer=\clozeshortanswer
+ \let\endshortanswer=\endclozeshortanswer
+}
+
+\gdef\writeclozequestion{%
+ \writetomoodle{<question type="cloze">}%
+ \moodle@writecommondata%
+ \writetomoodle{</question>}%
+}%
+
+\NewEnviron{clozemulti}[1][]{%
+ \bgroup
+ \setkeys{moodle}{default grade=1}%
+ \setkeys{moodle}{#1}%
+ \expandafter\gatheritems\xa{\BODY}%
+ \let\moodle@questionheader=\gatheredheader
+ \ifhtmlizer@active
+ %HTML version
+ \def\moodle@clozemulti@output{}%
+ \xa\g@addto@macro\xa\moodle@clozemulti@output\xa{\moodle@questionheader}%
+ \def\clozemulti@coding{}%
+ \edef\clozemulti@coding{\otherlbrace\csname moodle@default grade\endcsname:}%
+ \ifcase\moodle@multi@mode\relax
+ % Case 0: dropdown box style
+ \g@addto@macro{\clozemulti@coding}{MULTICHOICE:}%
+ \or
+ % Case 1: vertical style
+ \g@addto@macro{\clozemulti@coding}{MULTICHOICE_V:}%
+ \else
+ % Case 2: horizontal radio buttons
+ \g@addto@macro{\clozemulti@coding}{MULTICHOICE_H:}%
+ \fi
+ \bgroup
+ \setkeys{moodle}{feedback={}}%
+ \loopthroughitemswithcommand{\saveclozemultichoiceanswer}%
+ \egroup
+ \xa\g@addto@macro\xa\clozemulti@coding\xa{\otherrbrace}%
+ \xa\g@addto@macro\xa\moodle@clozemulti@output\xa{\clozemulti@coding}%
+ \xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozemulti@output}%
+ \def\endclozemulti@code{\htmlize@patchendenvironment}%
+ \else
+ %LaTeX version
+ \moodle@questionheader% %Any introductory text just continues to be typeset.
+ \def\cloze@multichoice@table@text{}%
+ \loopthroughitemswithcommand{\moodle@print@clozemultichoice@answer}%
+ \ifcase\moodle@multi@mode\relax
+ %Case 0: dropdown box style
+ \begin{tabular}[t]{|l|}\firsthline% (\firsthline is from the array package.)
+ \cloze@multichoice@table@text%
+ \end{tabular}%
+ \or
+ %Case 1: vertical style
+ \begin{itemize}\setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \cloze@multichoice@table@text%
+ \end{itemize}%
+ \else
+ %Case 2: horizontal radio buttons
+ \par{\cloze@multichoice@table@text}\par%
+ \fi
+ \def\endclozemulti@code{\relax}%
+ \fi
+ \passvalueaftergroup\endclozemulti@code%
+ \passvalueaftergroup\htmlize@afteraction@hook%
+ \egroup%
+}[\endclozemulti@code]%
+
+\def\moodle@print@clozemultichoice@answer#1{%
+ \moodle@print@clozemultichoice@answer@int#1\@rdelim%
+}%
+\newcommand\moodle@print@clozemultichoice@answer@int[1][]{%
+ \moodle@print@clozemultichoice@answer@int@int%
+}%
+\def\moodle@print@clozemultichoice@answer@int@int#1#2\@rdelim{%
+ % Case 0: "(answer) \\ \hline"
+ % Case 1: "\item (answer)"
+ % Case 2: "$\bullet~$(answer)\hfill"
+ \ifcase\moodle@multi@mode\relax
+ \relax% Case 0
+ \or
+ \g@addto@macro\cloze@multichoice@table@text{\item}% Case 1
+ \else
+ \g@addto@macro\cloze@multichoice@table@text{$\bullet~$}% Case 2
+ \fi
+ \def\test@i{#1}%
+ \ifx\test@i\@star
+ \g@addto@macro\cloze@multichoice@table@text{#2$~\checkmark$}%
+ \else
+ \g@addto@macro\cloze@multichoice@table@text{#1#2}%
+ \fi
+ \ifcase\moodle@multi@mode\relax
+ \g@addto@macro{\cloze@multichoice@table@text}{\\ \hline}% Case 0
+ \or
+ \relax% Case 1
+ \else
+ \g@addto@macro{\cloze@multichoice@table@text}{\hfill}% Case 2
+ \fi
+}%
+
+\def\saveclozemultichoiceanswer#1{%
+ \bgroup
+ \saveclozemultichoiceanswer@int#1\moodle@answer@rdelim
+ \egroup
+}%
+\newcommand\saveclozemultichoiceanswer@int[1][]{%
+ \setkeys{moodle}{fraction=0,#1}%
+ \saveclozemultichoiceanswer@int@int%
+}%
+\def\saveclozemultichoiceanswer@int@int#1#2\moodle@answer@rdelim{%
+ \def\test@i{#1}%
+ \ifgatherbeginningofloop\else
+ \xa\gdef\xa\clozemulti@coding\xa{\clozemulti@coding\clozetilde}% separator between answers
+ \fi
+ \ifx\test@i\@star
+ \setkeys{moodle}{fraction=100}%
+ \def\moodle@answertext{#2}%
+ \else
+ \def\moodle@answertext{#1#2}%
+ \fi
+ \trim@spaces@in\moodle@answertext
+ \ifx\moodle@fraction\@hundred
+ \g@addto@macro\clozemulti@coding{=}%
+ \fi
+ \ifnum0<\moodle@fraction\relax
+ \ifnum\moodle@fraction<100\relax
+ \xdef\clozemulti@coding{\expandonce\clozemulti@coding\otherpercent\moodle@fraction\otherpercent}%
+ \fi
+ \fi
+ \xdef\clozemulti@coding{\expandonce\clozemulti@coding\expandonce\moodle@answertext}%
+ \ifx\moodle@feedback\@empty\else
+ \xdef\clozemulti@coding{\expandonce\clozemulti@coding\otherbackslash\otherhash\moodle@feedback}%
+ \fi
+}%
+\NewEnviron{clozenumerical}[1][]{%
+ \bgroup
+ \expandafter\gatheritems\expandafter{\BODY}%
+ \let\moodle@questionheader=\gatheredheader
+ \setkeys{moodle}{default grade=1}%
+ \setkeys{moodle}{#1}%
+ \ifhtmlizer@active
+ %HTML version
+ \def\moodle@clozenumerical@output{}%
+ \xa\g@addto@macro\xa\moodle@clozenumerical@output\xa{\moodle@questionheader}%
+ \def\clozenumerical@coding{}%
+ \edef\clozenumerical@coding{\otherlbrace\csname moodle@default grade\endcsname:NUMERICAL:}%
+ \bgroup
+ \setkeys{moodle}{feedback={}}%
+ \loopthroughitemswithcommand{\saveclozenumericalanswer}%
+ \egroup
+ \xa\g@addto@macro\xa\clozenumerical@coding\xa{\otherrbrace}%
+ \xa\g@addto@macro\xa\moodle@clozenumerical@output\xa{\clozenumerical@coding}%
+ \xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozenumerical@output}%
+ \def\endclozenumerical@code{\htmlize@patchendenvironment}%
+ \else
+ %LaTeX version
+ \moodle@questionheader% %Any introductory text just continues to be typeset.
+ \def\cloze@numerical@table@text{}%
+ \loopthroughitemswithcommand{\moodle@print@clozenumerical@answer}%
+ \begin{tabular}[t]{|ll|}\firsthline
+ \cloze@numerical@table@text\hline%
+ \end{tabular}%
+ \def\endclozenumerical@code{\relax}%
+ \fi
+ \passvalueaftergroup\endclozenumerical@code%
+ \passvalueaftergroup\htmlize@afteraction@hook%
+ \egroup
+}[\endclozenumerical@code]%
+
+\def\moodle@print@clozenumerical@answer#1{%
+ \bgroup
+ \moodle@print@clozenumerical@answer@int#1\@rdelim
+ \egroup
+}%
+\newcommand\moodle@print@clozenumerical@answer@int[1][]{%
+ \setkeys{moodle}{#1}%
+ \moodle@print@clozenumerical@answer@int@int%
+}%
+\def\moodle@print@clozenumerical@answer@int@int#1\@rdelim{%
+ \ifx\moodle@fraction\@hundred
+ \def\moodle@clozenumericalprint@fraction{$\checkmark$}%
+ \else
+ \edef\moodle@clozenumericalprint@fraction{(\moodle@fraction\%)}%
+ \fi
+ \ifdim0pt=\moodle@tolerance pt\relax
+ \def\moodle@clozenumericalprint@tolerance{}%
+ \else
+ \edef\moodle@clozenumericalprint@tolerance{\noexpand\pm\moodle@tolerance}%
+ \fi
+ \xdef\moodle@clozenumericalprint@line{$#1\moodle@clozenumericalprint@tolerance$ & \moodle@clozenumericalprint@fraction}%
+ \xa\g@addto@macro\xa\cloze@numerical@table@text\xa{\moodle@clozenumericalprint@line \\}%
+}%
+
+\def\saveclozenumericalanswer#1{%
+ \bgroup
+ \saveclozenumericalanswer@int#1\moodle@answer@rdelim
+ \egroup
+}%
+\newcommand\saveclozenumericalanswer@int[1][]{%
+ \setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
+ \saveclozenumericalanswer@int@int%
+}%
+\def\saveclozenumericalanswer@int@int#1\moodle@answer@rdelim{%
+ \ifgatherbeginningofloop\else
+ \xa\gdef\xa\clozenumerical@coding\xa{\clozenumerical@coding\clozetilde}% separator between answers
+ \fi
+ \def\moodle@answertext{#1}%
+ \trim@spaces@in\moodle@answertext
+ \ifx\moodle@fraction\@hundred
+ \g@addto@macro\clozenumerical@coding{=}%
+ \fi
+ \ifnum0<\moodle@fraction\relax
+ \ifnum\moodle@fraction<100\relax
+ \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\otherpercent\moodle@fraction\otherpercent}%
+ \fi
+ \fi
+ \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\moodle@answertext:\moodle@tolerance}%
+ \ifx\moodle@feedback\@empty\else
+ \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\otherbackslash\otherhash\moodle@feedback}%
+ \fi
+}%
+\NewEnviron{clozeshortanswer}[1][]{%
+ \bgroup
+ \expandafter\gatheritems\expandafter{\BODY}%
+ \let\moodle@questionheader=\gatheredheader
+ \setkeys{moodle}{default grade=1}%
+ \setkeys{moodle}{#1}%
+ %Because nesting conditionals built by \csname doesn't work well,
+ %we'll test '\ifmoodle@case sensitive' now and save the result in \count0.
+ \csname ifmoodle@case sensitive\endcsname
+ \count0=1\relax
+ \else
+ \count0=0\relax
+ \fi
+ \ifhtmlizer@active
+ %HTML version
+ \def\moodle@clozeshortanswer@output{}%
+ \xa\g@addto@macro\xa\moodle@clozeshortanswer@output\xa{\moodle@questionheader}%
+ \def\clozeshortanswer@coding{}%
+ \ifnum\count0=1\relax
+ \edef\clozeshortanswer@coding{\otherlbrace\csname moodle@default grade\endcsname:SHORTANSWER_C:}%
+ \else
+ \edef\clozeshortanswer@coding{\otherlbrace\csname moodle@default grade\endcsname:SHORTANSWER:}%
+ \fi
+ \bgroup
+ \setkeys{moodle}{feedback={}}%
+ \loopthroughitemswithcommand{\saveclozeshortansweranswer}%
+ \egroup
+ \xa\g@addto@macro\xa\clozeshortanswer@coding\xa{\otherrbrace}%
+ \xa\g@addto@macro\xa\moodle@clozeshortanswer@output\xa{\clozeshortanswer@coding}%
+ \xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozeshortanswer@output}%
+ \def\endclozeshortanswer@code{\htmlize@patchendenvironment}%
+ \else
+ %LaTeX version
+ \moodle@questionheader% %Any introductory text just continues to be typeset.
+ \def\cloze@shortanswer@table@text{}%
+ \loopthroughitemswithcommand{\moodle@print@clozeshortanswer@answer}%
+ \ifnum\count0=1\relax
+ \marginpar{\tiny\mbox{(Case-Sensitive)}}%
+ \fi
+ \begin{tabular}[t]{|ll|}\firsthline
+ \cloze@shortanswer@table@text\hline%
+ \end{tabular}%
+ \def\endclozeshortanswer@code{\relax}%
+ \fi
+ \passvalueaftergroup\endclozeshortanswer@code%
+ \passvalueaftergroup\htmlize@afteraction@hook%
+ \egroup
+}[\endclozeshortanswer@code]%
+
+\def\moodle@print@clozeshortanswer@answer#1{%
+ \bgroup
+ \moodle@print@clozeshortanswer@answer@int#1\@rdelim
+ \egroup
+}%
+\newcommand\moodle@print@clozeshortanswer@answer@int[1][]{%
+ \setkeys{moodle}{#1}%
+ \moodle@print@clozeshortanswer@answer@int@int%
+}%
+\def\moodle@print@clozeshortanswer@answer@int@int#1\@rdelim{%
+ \ifx\moodle@fraction\@hundred
+ \def\moodle@clozeshortanswerprint@fraction{$\checkmark$}%
+ \else
+ \edef\moodle@clozeshortanswerprint@fraction{(\moodle@fraction\%)}%
+ \fi
+ \xdef\moodle@clozeshortanswerprint@line{#1 & \moodle@clozeshortanswerprint@fraction}%
+ \xa\g@addto@macro\xa\cloze@shortanswer@table@text\xa{\moodle@clozeshortanswerprint@line \\}%
+}%
+
+\def\saveclozeshortansweranswer#1{%
+ \bgroup
+ \saveclozeshortansweranswer@int#1\moodle@answer@rdelim
+ \egroup
+}%
+\newcommand\saveclozeshortansweranswer@int[1][]{%
+ \setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
+ \saveclozeshortansweranswer@int@int%
+}%
+\def\saveclozeshortansweranswer@int@int#1\moodle@answer@rdelim{%
+ \ifgatherbeginningofloop\else
+ \xa\gdef\xa\clozeshortanswer@coding\xa{\clozeshortanswer@coding\clozetilde}% separator between answers
+ \fi
+ \def\moodle@answertext{#1}%
+ \trim@spaces@in\moodle@answertext
+ \ifx\moodle@fraction\@hundred
+ \g@addto@macro\clozeshortanswer@coding{=}%
+ \fi
+ \ifnum0<\moodle@fraction\relax
+ \ifnum\moodle@fraction<100\relax
+ \xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\otherpercent\moodle@fraction\otherpercent}%
+ \fi
+ \fi
+ \xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\moodle@answertext}%
+ \ifx\moodle@feedback\@empty\else
+ \xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\otherbackslash\otherhash\moodle@feedback}%
+ \fi
+}%
+{\catcode`\#=12\gdef\otherhash{#}%
+ \catcode`\~=12\gdef\othertilde{~}%
+ \catcode`\&=12\gdef\otherampersand{&}%
+ \catcode`\^=12\gdef\othercaret{^}%
+ \catcode`\$=12\gdef\otherdollar{$}%
+ \catcode`\%=12\gdef\otherpercent{%}}%
+{\catcode`\ =12\gdef\otherspace{ }}%
+{\tt\catcode`\|=0\catcode`\\=12\relax|gdef|otherbackslash{\}}%
+{\catcode`\[=1\catcode`\]=2\catcode`\{=12\catcode`\}=12%
+ \gdef\otherlbrace[{]\gdef\otherrbrace[}]]
+
+\edef\@otherlbrace{\otherlbrace}%
+\edef\@otherrbrace{\otherrbrace}%
+\edef\@otherdollar{\otherdollar}%
+\edef\@otherbackslash{\otherbackslash}%
+\edef\@othertilde{\othertilde}%
+{ \catcode`\[=1\relax
+ \catcode`\]=2\relax
+ \catcode`\|=0\relax
+ |gdef|verbcatcodesweirdest[
+ |catcode`\{=12|relax
+ |catcode`\}=12|relax
+ |catcode`\\=12|relax
+ ]%
+}%
+\def\verbcatcodes{%
+ \catcode`\$=12\relax
+ \catcode`\&=12\relax
+ \catcode`\#=12\relax
+ \catcode`\^=12\relax
+ \catcode`\_=12\relax
+ \catcode`\~=12\relax
+ \makeatletter
+ \catcode`\%=12\relax
+ \catcode`\ =12\relax\catcode\newlinechar=12\verbcatcodesweirdest}%
+
+\def\normalcatcodes{%
+ \catcode`\\=0\relax
+ \catcode`\{=1\relax
+ \catcode`\}=2\relax
+ \catcode`\$=3\relax
+ \catcode`\&=4\relax
+ \catcode\endlinechar=5\relax
+ \catcode`\#=6\relax
+ \catcode`\^=7\relax
+ \catcode`\_=8\relax
+ \catcode`\ =10\relax
+ \makeatletter% We will be detokenizing and retokenizing internal control sequences, so we need this.
+ \catcode`\~=13\relax
+ \catcode`\%=14\relax}%
+
+\def\retokenizingcatcodes{%
+ %For rescanning previously scanned text, all true comments will already be gone,
+ %but % signs may have been inserted by Cloze questions, so we want to treat them as 'other.'
+ %
+ % TODO: #'s are more worrisome.
+ \normalcatcodes
+ \catcode`\%=12\relax
+}
+\begingroup
+ \catcode`\^^A=13\gdef^^A{\gdef\stm@saved}%
+ \catcode`\^^B=1\catcode`\^^C=2\relax
+ \long\gdef\scantokens@to@macro#1#2#3{%
+ % #1 = control sequence to be defined
+ % #2 = command to change catcodes, e.g. \verbcatcodes,
+ % and define any command sequences
+ % #3 = text to be retokenized and saved into #1.
+ \bgroup
+ \def\texttorescan{#3}%
+ \catcode`\^^A=13\catcode`\^^B=1\catcode`\^^C=2\relax
+ \xa\def\xa\arg\xa{\xa^^A\xa^^B\texttorescan^^C}%
+ #2%
+ \catcode\endlinechar=9\relax%
+ %\scantokens always sees an end-of-line character at its end and converts it to a space.
+ %The catcode change sets \scantokens to ignore end-of-line chars.
+ %In practice, we're always calling \scantokens on previously scanned text anyway,
+ %so we won't miss any real end-of-line chars, since they were already converted to spaces.
+ \xa\scantokens\xa{\arg}%
+ \egroup
+ \xa\def\xa#1\xa{\stm@saved}%
+ }%
+\endgroup%
+
+\long\def\ultradetokenize@to@macro#1#2{%
+ \scantokens@to@macro#1{\verbcatcodes}{#2}%
+}%
+\def\retokenizenormal@to@macro#1#2{%
+ \scantokens@to@macro#1{\retokenizingcatcodes}{#2}%
+}%
+\newcount\moodle@mathmodedepth
+\moodle@mathmodedepth=0\relax
+\def\moodle@ifmathmode#1#2{%
+ \ifnum\moodle@mathmodedepth>0\relax
+ #1%
+ \else
+ #2%
+ \fi
+}
+
+\newcount\grouplevel
+
+\newif\ifhtmlizer@active
+\htmlizer@activefalse
+\long\def\htmlize@grabblock#1#2\htmlize@rdelim@ii{%
+ \long\def\htmlize@blockinbraces{#1}%
+ \long\def\htmlize@remainder{#2}%
+}%
+\ultradetokenize@to@macro\@htmlize@stop@detokenized{\@htmlize@stop}%
+\xa\def\xa\htmlize@remove@stopcode\xa#\xa1\@htmlize@stop@detokenized{#1}%
+\newif\ifhtmlize@actioncs
+\newif\ifhtmlize@expandcs
+\newif\ifhtmlize@passcs
+
+\long\def\@@begin@cs{\begin}%
+\def\@@htmlize@stop{\@htmlize@stop}%
+
+\long\def\converttohtmlmacro#1#2{%
+ \grouplevel=0\relax
+ \def\htmlize@output{}%
+ \htmlizer@activetrue%
+ \converttohtml@int{#2}%
+ \htmlizer@activefalse%
+ \let#1=\htmlize@output\relax
+}
+
+\long\def\converttohtml@int#1{%
+ \advance\grouplevel by 1\relax
+ \bgroup
+ \ultradetokenize@to@macro\htmlize@texttoscan{#1}%
+ \xa\htmlize@recursive@i\htmlize@texttoscan\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i
+ \egroup
+ \advance\grouplevel by -1\relax
+}%
+
+\def\@lt{<}%
+\def\@gt{>}%
+
+\long\def\htmlize@recursive@i#1#2#3\htmlize@rdelim@i{%
+ % #1#2#3 is a sequence of tokens. All should be categories 11 (letter) or 12 (other).
+ % It terminates with the control sequences \@htmlize@stop\@htmlize@stop\@htmlize@stop.
+ %\long\def\ds{(#1|#2|#3)}\show\ds
+ \def\test@i{#1}%
+ \def\test@ii{#2}%
+ \ifx\test@i\@@htmlize@stop
+ \let\htmlize@next@i=\relax
+ \else
+ \ifx\test@i\@otherlbrace%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\otherlbrace}%
+ \bgroup
+ \normalcatcodes
+ %We need to rescan the input as TeX code,
+ % so TeX can automatically pull off the first group in braces.
+ % First, let's get rid of the terminal \@htmlize@stop codes.
+ {\def\@htmlize@stop{}\xdef\htmlize@scrap{#1#2#3}}%
+ \let\htmlize@text@to@rescan=\htmlize@scrap%
+ % Next, we retokenize the code.
+ \xa\retokenizenormal@to@macro\xa\htmlize@rescanned\xa{\htmlize@text@to@rescan}%
+ % Now break it up into two pieces.
+ \xa\htmlize@grabblock\htmlize@rescanned\@htmlize@stop\htmlize@rdelim@ii%
+ % The first piece, \htmlize@blockinbraces, will be passed as a unit to \converttohtml@int.
+ % The second part, \htmlize@remainder, will continue at this depth of grouping.
+ % Therefore we'll detokenize \htmlize@remainder here.
+ \xa\ultradetokenize@to@macro\xa\htmlize@remainder@detokenized\xa{\htmlize@remainder}%
+ \edef\htmlize@remainder@detokenized{\xa\htmlize@remove@stopcode\htmlize@remainder@detokenized}%
+ %
+ % Now build \htmlize@next@i.
+ % When done, should look like
+ % \converttohtml@int{\htmlize@blockinbraces}%
+ % \g@addto@macro\htmlize@output{\otherrbrace}%
+ % \htmlize@recursive@i\htmlize@remainder@detokenized\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i%
+ % but with all three arguments expanded.
+ % Note that we are running
+ \gdef\htmlize@scrap{\converttohtml@int}%
+ \xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\htmlize@blockinbraces}}%
+ \g@addto@macro\htmlize@scrap{\g@addto@macro\htmlize@output}%
+ \xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\otherrbrace}}%
+ \g@addto@macro\htmlize@scrap{\htmlize@recursive@i}%
+ \xa\g@addto@macro\xa\htmlize@scrap\xa{\htmlize@remainder@detokenized\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i}%
+ % Okay, that's done. It's stored in a global macro.
+ % Now we get it out of this group.
+ \egroup
+ \let\htmlize@next@i=\htmlize@scrap
+ \else
+ \ifx\test@i\@otherdollar%
+ % Math shift character.
+ \ifx\test@ii\@otherdollar
+ % Double dollar sign, so we're entering display math mode.
+ % We grab everything between $$...$$, sanitize it, and add it verbatim to
+ % our output.
+ \htmlize@displaymathshift@replace#1#2#3\htmlize@rdelim@iii%
+ \else
+ % Single dollar sign, so we're entering inline math mode.
+ % We grab everything between $$...$$, sanitize it, and add it verbatim to
+ % our output.
+ \htmlize@inlinemathshift@replace#1#2#3\htmlize@rdelim@iii%
+ \fi
+ % Now we resume work.
+ % The \htmlize@xxxxxxmathshift@replace macro stored the remaining text in \htmlize@remaining@text.
+ % Note that since we never detokenized and retokenized #1#2#3,
+ % \htmlize@remaining@text still includes the terminating \@htmlize@stop\@htmlize@stop\@htmlize@stop.
+ \def\htmlize@next@i{\xa\htmlize@recursive@i\htmlize@remaining@text\htmlize@rdelim@i}%
+ \else
+ \ifx\test@i\@otherbackslash%
+ % Control sequence. Oh boy.
+ % There are three possible things to do:
+ % 1. Retokenize everything, so we get a token list.
+ % Expand this control sequence, the first one in the list,
+ % to obtain a new token list. Then resume processing that list.
+ % Examples: \def\emph#1{<EM>#1</EM>}, \def\rec#1{\frac{1}{#1}}, \def\inv{^{-1}}
+ % \& --> &amp; \# --> #; etc.
+ % Environments: \begin{center}...\end{center} --> <CENTER>...</CENTER>
+ % 2. Retokenize everything, so we get a token list.
+ % Let this first command (with its parameters) ACT.
+ % This may involve work in TeX's stomach (e.g., with counters)
+ % or with external files (e.g., image processing).
+ % The command may directly add material to \htmlize@output,
+ % but it should not typeset anything and should vanish from the
+ % input stream when it is done.
+ % When it's done, we somehow need to detokenize and resume
+ % processing the remainder of the input stream.
+ % Only commands explicitly crafted (or modified) to work
+ % with moodle.sty can possibly do all this!
+ % Examples: (modified) \includegraphics
+ % Environments: \begin{clozemulti}, \begin{enumerate}
+ % 3. Ignore that it's a command. Pass it right on as a character
+ % sequence to \htmlize@output.
+ % Examples: \alpha, \frac
+ % Environments: \begin{array}
+ %
+ % #2 is only for items on a specific list.
+ % #1 is anything that runs in TeX's mouth.
+ % We could keep a list and give users a way to add to it.
+ % I could also try expanding macros, using \ifcsmacro from etoolbox.sty
+ %
+ % The first step is to figure out what control sequence we're dealing with.
+ % First, let's get rid of the terminal \@htmlize@stop codes.
+ {\def\@htmlize@stop{}\xdef\htmlize@scrap{#1#2#3}}%
+ \let\htmlize@text@to@rescan=\htmlize@scrap%
+ % Next, we retokenize the code.
+ \xa\retokenizenormal@to@macro\xa\htmlize@rescanned\xa{\htmlize@text@to@rescan}%
+ % Now break it up into two pieces.
+ \xa\htmlize@grabblock\htmlize@rescanned\@htmlize@stop\htmlize@rdelim@ii%
+ \let\@htmlize@cs\htmlize@blockinbraces%
+ \edef\htmlize@cs@string{\xa\string\@htmlize@cs}%
+ % The first piece, \htmlize@blockinbraces, will contain the single token in \@htmlize@cs.
+ % We'll need to keep the second part, \htmlize@remainder, since it probably
+ % contains arguments to the cs in \@htmlize@cs.
+ %\edef\ds{Encountered '\xa\string\@htmlize@cs'}\show\ds
+ %
+ % N.B. that \@htmlize@cs is a macro *containing* a single control sequence.
+ % This is good for testing with \ifx.
+ % \htmlize@cs@string contains the cs as a string, e.g., the characters "\emph".
+ %
+ \ifx\@htmlize@cs\@@begin@cs
+ %This is a \begin. Begin environment-handling routine.
+ %
+ % Grab the first {...} from \htmlize@remainder, which is the argument
+ % to \begin.
+ \xa\htmlize@grabblock\htmlize@remainder\@htmlize@stop\htmlize@rdelim@ii%
+ \let\htmlize@envname=\htmlize@blockinbraces%
+ %We do not need the rest, so we won't pay any attention to the new
+ %content of \htmlize@remainder.
+ %
+ %Now environments are non-expandable,
+ %so there are only two possibilities: action or pass.
+ \xa\ifinlist\xa{\htmlize@envname}{\htmlize@env@actionlist}%
+ {% Action environment!
+ %\bgroup
+ %\def\ds{Encountered active environment \string\begin\{{\htmlize@envname}\}}\show\ds
+ \def\htmlize@next@i{\xa\htmlize@do@actionenv\htmlize@rescanned\@htmlize@stop\htmlize@actionsequence@rdelim}%
+ %The \bgroup is to active the environments.
+ %The matching \egroup is found in \htmlize@do@actionenv.
+ }{%An environment to pass to the HTML
+ %We just pass the backslash from "\begin" and move on.
+ \g@addto@macro\htmlize@output{#1}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ }%
+ \else%
+ %This is not an environment. Begin macro-handling routine.
+ \htmlize@actioncsfalse
+ \htmlize@expandcsfalse
+ \htmlize@passcsfalse
+ \xa\ifinlist\xa{\htmlize@cs@string}{\htmlize@cs@actionlist}%
+ {%Action sequence!
+ \htmlize@actioncstrue}%
+ {% Not action sequence!
+ \xa\ifinlist\xa{\htmlize@cs@string}{\htmlize@cs@expandlist}%
+ {%CS to be expanded!
+ \htmlize@expandcstrue%
+ }%
+ {%CS to be transcribed to XML
+ \htmlize@passcstrue%
+ }%
+ }%
+ %Now exactly one of \ifhtmlize@actioncs, \ifhtmlize@expandcs, and \ifhtmlize@passcs is true.
+ \ifhtmlize@actioncs
+ % It's an action-sequence.
+ %\edef\ds{Must let \xa\string\@htmlize@cs\ act!}\show\ds
+ %\show\htmlize@rescanned
+ \def\htmlize@next@i{\xa\htmlize@do@actioncs\htmlize@rescanned\@htmlize@stop\htmlize@actionsequence@rdelim}%
+ %\show\htmlize@rescanned
+ % Note that \htmlize@do@actioncs should patch the command to have it
+ % restart the scanning in time.
+ \else
+ \ifhtmlize@expandcs
+ % control sequence to be expanded
+ %\edef\ds{Must expand \xa\string\@htmlize@cs}\show\ds
+ \bgroup
+ \htmlize@redefine@expansionmacros
+ %The \expandafters first expand \htmlize@rescanned,
+ %and then expand its first token just once.
+ \xa\xa\xa\gdef\xa\xa\xa\htmlize@scrap\xa\xa\xa{\htmlize@rescanned}%
+ \egroup
+ \xa\ultradetokenize@to@macro\xa\htmlize@remaining@text\xa{\htmlize@scrap}%
+ \def\htmlize@next@i{\xa\htmlize@recursive@i\htmlize@remaining@text\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i}%
+ \else
+ % control sequence to be transcribed to XML.
+ %\edef\ds{Must pass on \xa\string\@htmlize@cs}\show\ds
+ \g@addto@macro\htmlize@output{#1}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \fi
+ \fi
+ \fi
+ \else%
+ \ifx\test@i\@othertilde%
+ % The ~ becomes non-breaking space &nbsp;
+ \g@addto@macro\htmlize@output{\otherampersand nbsp;}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \else
+ \ifx\test@i\@lsinglequote%
+ \ifx\test@ii\@lsinglequote%
+ % Double left quote
+ \g@addto@macro\htmlize@output{\otherampersand ldquo;}%
+ \def\htmlize@next@i{\htmlize@recursive@i#3\htmlize@rdelim@i}%
+ \else
+ \g@addto@macro\htmlize@output{\otherampersand lsquo;}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \fi
+ \else
+ \ifx\test@i\@rsinglequote%
+ \ifx\test@ii\@rsinglequote%
+ %Double right quote
+ \g@addto@macro\htmlize@output{\otherampersand rdquo;}%
+ \def\htmlize@next@i{\htmlize@recursive@i#3\htmlize@rdelim@i}%
+ \else
+ \g@addto@macro\htmlize@output{\otherampersand rsquo;}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \fi
+ \else
+ \ifx\test@i\@doublequote
+ \g@addto@macro\htmlize@output{\otherampersand rdquo;}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \else
+ \ifx\test@i\@lt
+ \moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherampersand lt;}}%
+ {\g@addto@macro\htmlize@output{<}}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \else
+ \ifx\test@i\@gt
+ \moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherampersand gt;}}%
+ {\g@addto@macro\htmlize@output{>}}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \else
+ % Default case: write first token to output, call self on remaining tokens.
+ \g@addto@macro\htmlize@output{#1}%
+ \def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \htmlize@next@i
+}%
+
+\def\@lsinglequote{`}%
+\def\@rsinglequote{'}%
+\def\@doublequote{"}%
+\edef\inlinemathleftdelim{\otherbackslash(}%
+\def\inlinemathrightdelim#1{\advancemathmodecounter{-1}%
+ \g@addto@macro\htmlize@output{\otherbackslash)}}%
+\edef\displaymathleftdelim{<CENTER>\otherbackslash[}%
+\def\displaymathrightdelim#1{\advancemathmodecounter{-1}%
+ \g@addto@macro\htmlize@output{\otherbackslash]</CENTER>}}%
+{\catcode`\$=12\relax%
+ \gdef\htmlize@inlinemathshift@replace$#1$#2\htmlize@rdelim@iii{%
+ %\def\ds{inline math shift has '#1' and '#2'}\show\ds
+ \xa\g@addto@macro\xa\htmlize@output\xa{\inlinemathleftdelim}%
+ \advancemathmodecounter{1}%
+ \def\mathtext{#1}%
+ \def\aftertext{#2}%
+ \xdef\htmlize@remaining@text{\expandonce\mathtext%
+ \otherbackslash inlinemathrightdelim{}%
+ \expandonce\aftertext}%
+ %\show\htmlize@remaining@text
+ }%
+ \gdef\htmlize@displaymathshift@replace$$#1$$#2\htmlize@rdelim@iii{%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\displaymathleftdelim}%
+ \advancemathmodecounter{1}%
+ \def\mathtext{#1}%
+ \def\aftertext{#2}%
+ \xdef\htmlize@remaining@text{\expandonce\mathtext%
+ \otherbackslash displaymathrightdelim{}%
+ \expandonce\aftertext}%
+ }%
+}
+\long\def\htmlize@do@actionenv#1#2\@htmlize@stop\htmlize@actionsequence@rdelim{%
+ \bgroup %The corresponding \egroup is given in \htmlize@proceedwiththerest,
+ %to localize the changes to the environment definitions.
+ \htmlize@activate@environments
+ \gdef\htmlize@afteraction@hook{}%
+ #1#2\@htmlize@stop\htmlize@actionsequence@rdelim%
+}
+
+\def\htmlize@patchendenvironment{\swaptotrueendenvironment{\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook}}%
+
+\def\swaptotrueendenvironment#1#2\if@ignore\@ignorefalse\ignorespaces\fi{#2\if@ignore\@ignorefalse\ignorespaces\fi#1}%
+
+\long\def\htmlize@record@environment#1{%
+ \listadd{\htmlize@env@actionlist}{#1}%
+}
+\long\def\html@newenvironment#1#2{%
+ \listadd{\htmlize@env@actionlist}{#1}%
+ \g@addto@macro\htmlize@activate@environments{%
+ \xa\let\csname #1\endcsname\relax%
+ \xa\let\csname end#1\endcsname\relax%
+ \NewEnviron{#1}{%
+ #2%
+ }[\htmlize@patchendenvironment]%
+ }%
+}
+
+\def\htmlize@activate@environments{}%
+\gdef\htmlize@afteraction@hook{}%
+
+\long\def\htmlize@do@actioncs#1#2\htmlize@actionsequence@rdelim{%
+ % #1#2 contains the current string to be rendered into HTML;
+ % N.B. it has been tokenized at this point,
+ % so TeX can process it directly.
+ % #1 = the command sequence we need to execute
+ % #2 = the rest of the string
+ %
+ % First, we patch the desired command so that, when it is over,
+ % it calls \htmlize@proceedwiththerest.
+ % We do this within the group, so as not to permanently change the command.
+ \bgroup
+ % The matching \egroup is issued in \htmlize@proceedwiththerest,
+ % so that the changes made by \htmlize@activate@css are localized to just the command itself.
+ \gdef\htmlize@afteraction@hook{}%
+ \htmlize@activate@css%
+ \def\test@i{#1}%
+ \ifx\test@i\@relax
+ \def#1{\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook}%
+ \else
+ \xapptocmd#1{\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook}{}{\PackageError{Could not patch the command \string#1!}}%
+ \fi
+ % Now we call that patched command.
+ #1#2\htmlize@actionsequence@rdelim%
+ %The matching \egroup now is built into the command #1.
+}
+\long\def\htmlize@proceedwiththerest#1\htmlize@actionsequence@rdelim{%
+ % The action cs has done its work.
+ % Now we gather up the remaining tokens, detokenize them,
+ % remove the \@htmlize@stop, and get back to work transcribing it.
+ \egroup %This \egroup matches the \bgroup that was issued either in \htmlize@do@actioncs or in \htmlize@do@actionenv
+ \ultradetokenize@to@macro\htmlize@remainder@detokenized{#1}%
+ %This will contain an extra \@htmlize@stop, so we remove it.
+ \xa\xa\xa\def\xa\xa\xa\htmlize@remainder@detokenized\xa\xa\xa{\xa\htmlize@remove@stopcode\htmlize@remainder@detokenized}%
+ %Now we get back to work transcribing the remainder.
+ \xa\htmlize@recursive@i\htmlize@remainder@detokenized\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i%
+}
+
+\long\def\htmlize@record@action#1{%
+ \xa\listadd\xa\htmlize@cs@actionlist\xa{\string#1}%
+}
+
+\def\htmlize@activate@css{}%
+\def\html@action@def#1{%
+ \htmlize@record@action{#1}%
+ \xa\def\xa\htmlize@scrap\xa{\xa\let\xa#1\csname html@\string#1\endcsname}%
+ \xa\g@addto@macro\xa\htmlize@activate@css\xa{\htmlize@scrap}%
+ \xa\def\csname html@\string#1\endcsname% %And this \def\html@\oldcsname is follows by the remainder of the definition.
+}
+\def\htmlize@redefine@expansionmacros{}%
+\long\def\htmlize@record@expand#1{%
+ \xa\listadd\xa\htmlize@cs@expandlist\xa{\string#1}%
+}
+\let\htmlregister=\htmlize@record@expand
+\long\def\html@def#1{%
+ \htmlize@record@expand{#1}%
+ \xa\def\xa\htmlize@scrap\xa{\xa\let\xa#1\csname html@\string#1\endcsname}%
+ \xa\g@addto@macro\xa\htmlize@redefine@expansionmacros\xa{\htmlize@scrap}%
+ \xa\def\csname html@\string#1\endcsname%
+}
+\htmlize@record@environment{clozemulti}
+\htmlize@record@environment{multi}
+\htmlize@record@environment{clozenumerical}
+\htmlize@record@environment{numerical}
+\htmlize@record@environment{clozeshortanswer}
+\htmlize@record@environment{shortanswer}
+
+\html@newenvironment{center}{\xdef\htmlize@afteraction@hook{<CENTER>\expandonce\BODY</CENTER>}}%
+\html@newenvironment{enumerate}{%
+ \xa\gatheritems\xa{\BODY}%
+ \gdef\htmlize@afteraction@hook{<OL>}%
+ \loopthroughitemswithcommand{\moodle@itemtoLI}%
+ \g@addto@macro\htmlize@afteraction@hook{</OL>}%
+}%
+\html@newenvironment{itemize}{%
+ \xa\gatheritems\xa{\BODY}%
+ \gdef\htmlize@afteraction@hook{<UL>}%
+ \loopthroughitemswithcommand{\moodle@itemtoLI}%
+ \g@addto@macro\htmlize@afteraction@hook{</UL>}%
+}%
+\def\moodle@itemtoLI#1{%
+ \g@addto@macro\htmlize@afteraction@hook{<LI>#1</LI>}%
+}%
+
+\def\advancemathmodecounter#1{%
+ \global\advance\moodle@mathmodedepth by #1\relax
+}
+\htmlize@record@action{\advancemathmodecounter}%
+
+\htmlize@record@action{\relax}%
+
+\html@action@def\#{\g@addto@macro\htmlize@output{\otherhash}}%
+\html@action@def\&{\g@addto@macro\htmlize@output{\otherampersand}}%
+\html@action@def\\{\moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherbackslash\otherbackslash}}%
+ {\g@addto@macro\htmlize@output{<BR/>}}}%
+\html@action@def\{{%
+ \moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherbackslash\otherlbrace}}%
+ {\g@addto@macro\htmlize@output{\otherlbrace}}%
+ }%
+\html@action@def\}{%
+ \moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherbackslash\otherrbrace}}%
+ {\g@addto@macro\htmlize@output{\otherrbrace}}%
+ }%
+\html@action@def\ldots{%
+ \moodle@ifmathmode{\g@addto@macro\htmlize@output{\string\ldots}}%
+ {\g@addto@macro\htmlize@output{...}}%
+ }%
+\html@action@def\dots{%
+ \moodle@ifmathmode{\g@addto@macro\htmlize@output{\string\dots}}%
+ {\g@addto@macro\htmlize@output{...}}%
+ }%
+\html@action@def\ {%
+ \moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherbackslash\otherspace}}%
+ {\g@addto@macro\htmlize@output{\otherspace}}%
+ }%
+\html@action@def\${%
+ \g@addto@macro\htmlize@output{\otherdollar}%
+ }%
+
+\html@action@def\clozetilde{%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\othertilde}%
+ }%
+
+{\catcode`|=3\relax
+ \gdef\htmlize@vowels{a|e|i|o|u|A|E|I|O|U|}}
+\def\htmlize@define@diacritic#1#2{%
+ \htmlize@record@action{#1}%
+ \g@addto@macro\htmlize@activate@css{%
+ \def#1##1{%
+ \ifinlist{##1}{\htmlize@vowels}%
+ {\g@addto@macro\htmlize@output{\otherampersand##1#2;}}%
+ {\xa\g@addto@macro\htmlize@output\xa{\string#1##1}}%
+ }%
+ }%
+}
+\htmlize@define@diacritic{\^}{circ}%
+\htmlize@define@diacritic{\'}{acute}%
+\htmlize@define@diacritic{\"}{uml}%
+\htmlize@define@diacritic{\`}{grave}%
+
+\def\@o{o}\def\@O{O}\def\@u{u}\def\@U{U}%
+\html@action@def\H#1{%
+ \bgroup
+ \def\test@i{#1}%
+ \ifx\test@i\@O
+ \def\toadd{\otherampersand\otherhash337;}%
+ \else
+ \ifx\test@i\@o
+ \def\toadd{\otherampersand\otherhash337;}%
+ \else
+ \ifx\test@i\U
+ \def\toadd{\otherampersand\otherhash368;}%
+ \else
+ \ifx\test@i\u
+ \def\toadd{\otherampersand\otherhash369;}%
+ \else
+ \def\toadd{\otherbackslash\otherlbrace#1\otherrbrace}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \xa\g@addto@macro\xa\htmlize@output\xa{\toadd}%
+ \egroup
+}%
+
+{\catcode`|=3\relax
+ \gdef\htmlize@tilde{A|N|O|a|n|o|}}
+\html@action@def\~#1{%
+ \ifinlist{#1}{\htmlize@tilde}%
+ {\g@addto@macro\htmlize@output{\otherampersand#1tilde;}}%
+ {\xa\g@addto@macro\htmlize@output\xa{\string\~#1}}%
+ }%
+\html@def\underline#1{<SPAN STYLE="text-decoration: underline;">#1</SPAN>}
+\html@def\emph#1{<EM>#1</EM>}%
+\html@def\textbf#1{<B>#1</B>}%
+\html@def\blank{____________}%
+\html@def\par{</P><P>}%
+\html@def\aa{\&aring;}%
+\html@def\AA{\&Aring;}%
+\html@def\ae{\&aelig;}%
+\html@def\AE{\&AElig;}%
+\html@def\S{\&sect;}%
+\html@def\euro{\&euro;}%
+\html@def\texteuro{\&euro;}%
+\html@def\o{\&oslash;}%
+\html@def\O{\&Oslash;}%
+\html@def\ss{\&szlig;}%
+\html@def\l{\&lstrok;}%
+\html@def\L{\&Lstrok;}%
+
+\htmlize@record@expand{\inv}%
+\htmlize@record@expand{\rec}%
+
+\htmlize@record@action\inlinemathrightdelim
+\htmlize@record@action\displaymathrightdelim
+
+\def\htmlize@setexecutable#1{%
+ % Defines macro #1 to be #2 in a verbatim mode suitable for filenames
+ \def\htmlize@executable@macro{#1}%
+ \bgroup\catcode`\|=0\catcode`\\=12\relax%
+ \htmlize@setexecutable@int
+}
+\def\htmlize@setexecutable@int#1{%
+ \egroup
+ \expandafter\def\htmlize@executable@macro{#1}%
+}
+
+\def\ghostscriptcommand{\htmlize@setexecutable\gs}
+\def\opensslcommand{\htmlize@setexecutable\openssl}
+\def\imagemagickcommand{\htmlize@setexecutable\htmlize@imagemagick@convert}
+
+\ifwindows%
+ \ghostscriptcommand{gswin64c.exe}%
+\else%
+ \ghostscriptcommand{gs}%
+\fi%
+
+\opensslcommand{openssl}%
+\imagemagickcommand{convert}%
+\define@cmdkeys{moodle@includegraphics}[moodle@graphics@]{ppi}
+\define@cmdkey{moodle}[moodle@graphics@]{ppi}{}% This is so the ppi key can be set at the document, quiz, or question level.
+\define@cmdkeys{Gin}{ppi}% This is so the original \includegraphics will not object to a key of ppi.
+\setkeys{moodle@includegraphics}{ppi=103}
+
+\newdimen\moodle@graphics@temp@dimen
+\newcount\moodle@graphics@height@pixels
+\newcount\moodle@graphics@width@pixels
+\def\moodle@graphics@dimentopixels#1#2{%
+ \moodle@graphics@temp@dimen=#2\relax
+ \moodle@graphics@temp@dimen=0.013837\moodle@graphics@temp@dimen
+ \xa\moodle@graphics@temp@dimen\xa=\moodle@graphics@ppi\moodle@graphics@temp@dimen
+ #1=\moodle@graphics@temp@dimen
+ \divide #1 by 65536\relax
+}
+\define@key{moodle@includegraphics}{height}[]{%
+ \moodle@graphics@dimentopixels{\moodle@graphics@height@pixels}{#1}%
+}
+\define@key{moodle@includegraphics}{width}[]{%
+ \moodle@graphics@dimentopixels{\moodle@graphics@width@pixels}{#1}%
+}
+\setkeys{moodle@includegraphics}{height=0pt,width=0pt}
+\html@action@def\includegraphics{\moodle@includegraphics@int}%
+ % Note that \htmlize@do@actioncs will 'patch' this by putting
+ % '\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook'
+ % at the end. We want those 3 tokens to occur instead after
+ % the graphics filename.
+\def\moodle@includegraphics@int#1#2#3{\moodle@includegraphics@int@int}%
+ % This gobbles up those three spurious tokens,
+ % which we will re-insert after our work is done.
+\newcommand\moodle@includegraphics@int@int[2][]{%
+ \bgroup% The grouping is to localize the changes caused by \setkeys.
+ \message{moodle.sty: Processing \string\includegraphics[#1]{#2} for HTML...^^J}
+ \setkeys*{moodle@includegraphics}{#1}%
+ % Height or width should be given in TeX dimensions like cm or pt or in,
+ % and are converted to pixels for web use using the ppi key.
+ % TO DO: Can we modify \includegraphics to accept height or width in
+ % pixels?
+ % TO DO: What about \includegraphics[scale=0.7] ?
+ % Other keys: keepaspectratio=true|false, angle (rotation), clip & trim
+ \ifnum\moodle@graphics@height@pixels=0\relax
+ \ifnum\moodle@graphics@width@pixels=0\relax
+ % No size specified. Default to height of 200 pixels.
+ \def\moodle@graphics@geometry{x200}%
+ \def\moodle@graphics@htmlgeometry{}%
+ \else
+ % Width only specified.
+ \edef\moodle@graphics@geometry{\number\moodle@graphics@width@pixels}%
+ \edef\moodle@graphics@htmlgeometry{width=\number\moodle@graphics@width@pixels}%
+ \fi
+ \else
+ \ifnum\moodle@graphics@width@pixels=0\relax
+ % Height only specified. The `x' is part of the syntax.
+ \edef\moodle@graphics@geometry{x\number\moodle@graphics@height@pixels}%
+ \edef\moodle@graphics@htmlgeometry{height=\number\moodle@graphics@height@pixels}%
+ \else
+ % Height and width both specified. The `!' is part of the syntax.
+ \edef\moodle@graphics@geometry{\number\moodle@graphics@width@pixels x\number\moodle@graphics@height@pixels!}%
+ \edef\moodle@graphics@htmlgeometry{width=\number\moodle@graphics@width@pixels\otherspace height=\number\moodle@graphics@height@pixels}%
+ \fi
+ \fi
+ %First, convert it to PNG
+ \edef\cmdline{\htmlize@imagemagick@convert\otherspace #2 -resize \moodle@graphics@geometry\otherspace #2.png}%
+ \message{moodle.sty: Converting '#2' to PNG...^^J}%
+ \expandafter\immediate\expandafter\write18\expandafter{\cmdline}%
+ %Next, convert the PNG to base64 encoding
+ \def\cmdline{\openssl\otherspace enc -base64 -in #2.png -out #2.enc}%
+ \message{moodle.sty: Converting '#2.png' to base64...^^J}%
+ \expandafter\immediate\expandafter\write18\expandafter{\cmdline}%
+ %Now, save that base64 encoding in a TeX macro
+ \def\moodle@newpic@baselxiv{}%
+ \message{moodle.sty: Reading base64 file '#2.enc'...^^J}%
+ \openin\baseLXIVdatafile=#2.enc\relax
+ \savebaselxivdata@recursive
+ \closein\baseLXIVdatafile
+ \xa\global\xa\let\csname picbaselxiv@graphics@#2\endcsname=\moodle@newpic@baselxiv%
+ \edef\htmlize@imagetag{<IMG \moodle@graphics@htmlgeometry\otherspace SRC="data:image/png;base64,\csname picbaselxiv@graphics@#2\endcsname">}%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\htmlize@imagetag}%
+ \message{moodle.sty: <IMG> tag inserted.^^J}%
+ \egroup
+ % Now we re-insert the code to get the HTMLizing going again.
+ \xa\htmlize@proceedwiththerest\htmlize@afteraction@hook
+}
+\newread\baseLXIVdatafile
+\def\savebaselxivdata@recursive{%
+ \ifeof\baseLXIVdatafile
+ \let\baselxiv@next=\relax
+ \else
+ \read\baseLXIVdatafile to \datalinein
+ %\message{<<\datalinein>>^^J}
+ \ifx\datalinein\@moodle@par
+ \let\baselxiv@next=\relax
+ \else
+ %We add tokens manually, rather than with \g@addto@macro, to save time.
+ \xa\xa\xa\gdef\xa\xa\xa\moodle@newpic@baselxiv\xa\xa\xa{\xa\moodle@newpic@baselxiv\datalinein^^J}%
+ \let\baselxiv@next=\savebaselxivdata@recursive
+ \fi
+ \fi
+ \baselxiv@next
+}
+\newif\ifmoodle@tikzloaded
+\moodle@tikzloadedfalse
+\AtBeginDocument{
+ \ifx\tikzpicture\@undefined
+ \moodle@tikzloadedfalse
+ \else
+ \moodle@tikzloadedtrue
+ \fi
+ \ifmoodle@tikzloaded
+ \usetikzlibrary{external}
+ \tikzexternalize%
+ \tikzset{external/force remake}%
+
+ \ifpdf
+ \def\pdftopng{\edef\gscmdline{\gs\otherspace -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png -r200 \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.pdf}%
+ \expandafter\immediate\expandafter\write18\expandafter{\gscmdline}}%
+ \else
+ \def\pstopng{\edef\gscmdline{\gs\otherspace -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png -r200 \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.ps}%
+ \expandafter\immediate\expandafter\write18\expandafter{\gscmdline}}%
+ \fi
+ \def\pngtobaselxiv{\edef\opensslcmdline{\openssl\otherspace enc -base64 -in \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png -out \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.enc}%
+ \expandafter\immediate\expandafter\write18\expandafter{\opensslcmdline}}%
+
+ \let\moodle@oldtikzpicture=\tikzpicture
+
+ %The following code lets us run things *before* the normal \begin{tikzpicture}.
+ \renewenvironment{tikzpicture}{%
+ \global\advance\numconvertedpictures by 1\relax
+ %\jobnamewithsuffixtomacro{\htmlize@picbasename}{-tikztemp-\the\numconvertedpictures}%
+ %\xa\tikzsetnextfilename\xa{\htmlize@picbasename}%
+ \tikzsetnextfilename{\tikzexternalrealjob-tikztemp-\the\numconvertedpictures}%
+ \moodle@oldtikzpicture%
+ }{}%
+ % However, the tikz externalize library does *not* run \end{tikzpicture}.
+ % In order to run commands after the tikz picture is done compiling, we need to
+ % use a hook into \tikzexternal@closeenvironments.
+
+ \g@addto@macro{\tikzexternal@closeenvironments}{%
+ \moodle@endtikzpicture@hook
+ }
+ \def\moodle@endtikzpicture@hook{%
+ \@moodle@ifgeneratexml{%
+ \ifpdf
+ \message{moodle.sty: Converting picture '\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.pdf' to PNG...^^J}%
+ \pdftopng
+ \else
+ \pstopng
+ \fi
+ \message{moodle.sty: Converting '\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png' to base64...^^J}%
+ \pngtobaselxiv
+ \message{moodle.sty: Reading base64 file '\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.enc'...^^J}%
+ \savebaselxivdata
+ \message{moodle.sty: base64 data saved.^^J}%
+ }{}%
+ }
+ \tikzset{external/optimize=true}
+ \tikzset{external/optimize command away={\VerbatimInput}{1}}
+ %
+ % The HTMLizer version of the tikzpicture environment,
+ % which writes an <IMG> tag to the XML file.
+ \htmlize@record@environment{tikzpicture}
+ \g@addto@macro\htmlize@activate@environments{%
+ \let\tikzpicture\relax\let\endtikzpicture\relax
+ \NewEnviron{tikzpicture}[1][]{%
+ \global\advance\numpicturesread by 1\relax
+ \edef\htmlize@imagetag{<IMG SRC="data:image/png;base64,\csname picbaselxiv@\the\numpicturesread\endcsname">}%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\htmlize@imagetag}%
+ }[\htmlize@patchendenvironment]%
+ }%
+ \else
+ %TikZ not loaded. Provide dummy definitions for commands.
+ \long\def\tikzifexternalizing#1#2{#2}%
+ \fi
+}
+
+\newcount\numconvertedpictures
+\numconvertedpictures=0\relax
+\newcount\numpicturesread
+\numpicturesread=0\relax
+
+\def\savebaselxivdata{%
+ \def\moodle@newpic@baselxiv{}%
+ \openin\baseLXIVdatafile=\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.enc\relax
+ \savebaselxivdata@recursive
+ \closein\baseLXIVdatafile
+ \xa\global\xa\let\csname picbaselxiv@\the\numconvertedpictures\endcsname=\moodle@newpic@baselxiv%
+}
+
+\def\@moodle@par{\par}%
+\AtEndDocument{%
+ \ifmoodle@tikzloaded
+ \@moodle@ifgeneratexml{%
+ \ifwindows
+ \immediate\write18{del \tikzexternalrealjob-tikztemp-*.*}%
+ \else
+ \immediate\write18{rm \tikzexternalrealjob-tikztemp-*.*}%
+ \fi
+ }{}%
+ \fi
+}
+
+\endinput
+%%
+%% End of file `moodle.sty'.