}%
\else
\writetomoodle{}%
\fi
\moodle@writecommondata%
\moodle@writesingle%
\moodle@writeshuffle%
\moodle@writeanswernumbering%
\moodle@writeanswers%
\writetomoodle{}%
}%
\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{}%
\moodle@writecommondata%
\writetomoodle{}%
}%
\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{#1}, \def\rec#1{\frac{1}{#1}}, \def\inv{^{-1}}
% \& --> & \# --> #; etc.
% Environments: \begin{center}...\end{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
\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{\otherbackslash[}%
\def\displaymathrightdelim#1{\advancemathmodecounter{-1}%
\g@addto@macro\htmlize@output{\otherbackslash]}}%
{\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{\expandonce\BODY}}%
\html@newenvironment{enumerate}{%
\xa\gatheritems\xa{\BODY}%
\gdef\htmlize@afteraction@hook{}%
\loopthroughitemswithcommand{\moodle@itemtoLI}%
\g@addto@macro\htmlize@afteraction@hook{
}%
}%
\html@newenvironment{itemize}{%
\xa\gatheritems\xa{\BODY}%
\gdef\htmlize@afteraction@hook{}%
\loopthroughitemswithcommand{\moodle@itemtoLI}%
\g@addto@macro\htmlize@afteraction@hook{
}%
}%
\def\moodle@itemtoLI#1{%
\g@addto@macro\htmlize@afteraction@hook{#1}%
}%
\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{
}}}%
\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{#1}
\html@def\emph#1{#1}%
\html@def\textbf#1{#1}%
\html@def\blank{____________}%
\html@def\par{}%
\html@def\aa{\å}%
\html@def\AA{\Å}%
\html@def\ae{\æ}%
\html@def\AE{\Æ}%
\html@def\S{\§}%
\html@def\euro{\€}%
\html@def\texteuro{\€}%
\html@def\o{\ø}%
\html@def\O{\Ø}%
\html@def\ss{\ß}%
\html@def\l{\ł}%
\html@def\L{\Ł}%
\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{}%
\xa\g@addto@macro\xa\htmlize@output\xa{\htmlize@imagetag}%
\message{moodle.sty: 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 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{}%
\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'.