summaryrefslogtreecommitdiff
path: root/tex/context/modules/mkxl
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2021-06-07 08:17:45 +0200
committerContext Git Mirror Bot <phg@phi-gamma.net>2021-06-07 08:17:45 +0200
commite3a0d092848f3f128742ffe478334651ab18e8dc (patch)
treed4ab51ab52cd72d343fe5d72b9e11adf81642460 /tex/context/modules/mkxl
parent75be509021abdcd01f7d5caf35d026647042322a (diff)
downloadcontext-e3a0d092848f3f128742ffe478334651ab18e8dc.tar.gz
2021-06-07 08:07:00
Diffstat (limited to 'tex/context/modules/mkxl')
-rw-r--r--tex/context/modules/mkxl/m-system-readers.mkxl148
-rw-r--r--tex/context/modules/mkxl/m-timing.mkxl113
-rw-r--r--tex/context/modules/mkxl/s-languages-goodies.lmt99
-rw-r--r--tex/context/modules/mkxl/s-languages-goodies.mkxl144
-rw-r--r--tex/context/modules/mkxl/s-system-macros.mkxl330
-rw-r--r--tex/context/modules/mkxl/s-system-tokens.mkxl84
-rw-r--r--tex/context/modules/mkxl/x-mathml.lmt910
-rw-r--r--tex/context/modules/mkxl/x-mathml.mkxl2448
8 files changed, 4276 insertions, 0 deletions
diff --git a/tex/context/modules/mkxl/m-system-readers.mkxl b/tex/context/modules/mkxl/m-system-readers.mkxl
new file mode 100644
index 000000000..0f2d3275e
--- /dev/null
+++ b/tex/context/modules/mkxl/m-system-readers.mkxl
@@ -0,0 +1,148 @@
+%D \module
+%D [ file=m-system-readers,
+%D version=2021.02.13,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Reading from files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startmodule[system-readers]
+
+% \unprotect
+%
+% \installcorenamespace {markedlines}
+%
+% \permanent\protected\def\startmarkedlines[#1]%
+% {\edef\scratchstring{#1}%
+% \scratchcounter\numexpr\inputlineno+\plusone\relax
+% \gobbleuntilandfinalize\stopmarkedlines}
+%
+% \permanent\protected\def\stopmarkedlines
+% {\edefcsname\??markedlines\scratchstring\endcsname
+% {{\the\scratchcounter}{\the\numexpr\inputlineno+\minusone\relax}}}
+%
+% \protected\def\firstmarkedline#1%
+% {\numexpr
+% \ifcsname\??markedlines#1\endcsname
+% \normalexpanded{\noexpand\firstoftwoarguments\lastnamedcs}%
+% \else
+% \zerocount
+% \fi
+% \relax}
+%
+% \protected\def\lastmarkedline#1%
+% {\numexpr
+% \ifcsname\??markedlines#1\endcsname
+% \normalexpanded{\noexpand\secondoftwoarguments\lastnamedcs}%
+% \else
+% \zerocount
+% \fi
+% \relax}
+%
+% \protected\def\markedlines#1%
+% {\ifcsname\??markedlines\scratchstring\endcsname\lastnamedcs\else{0}{0}\fi}
+%
+% \protect
+
+\startluacode
+
+ local createtoken = tokens.create
+ local gobbletoken = tokens.gobble
+ local integer_value = tokens.values.integer
+
+ local marked = { }
+
+ interfaces.implement {
+ name = "startmarkedlines",
+ public = true,
+ protected = true,
+ arguments = "optional",
+ actions = function(tag)
+ local start = status.readstate.linenumber + 1
+ gobbletoken(createtoken("startmarkedlines"),createtoken("stopmarkedlines"))
+ local state = status.readstate
+ marked[tag] = { state.filename, start, state.linenumber - 1 }
+ end
+ }
+
+
+ interfaces.implement {
+ name = "markedfilename",
+ public = true,
+ -- usage = "value",
+ arguments = "string",
+ actions = function(tag)
+ local m = marked[tag]
+ -- return m and m[1] or ""
+ context(m and m[1] or "")
+ end
+ }
+
+ interfaces.implement {
+ name = "firstmarkedline",
+ public = true,
+ usage = "value",
+ arguments = "string",
+ actions = function(tag)
+ local m = marked[tag]
+ return integer_value, m and m[2] or 0
+ end
+ }
+
+ interfaces.implement {
+ name = "lastmarkedline",
+ public = true,
+ usage = "value",
+ arguments = "string",
+ actions = function(tag)
+ local m = marked[tag]
+ return integer_value, m and m[3] or 0
+ end
+ }
+
+\stopluacode
+
+\continueifinputfile{m-system-readers.mkxl}
+
+\starttext
+
+\startmarkedlines[test]
+SOME LINE 1
+SOME LINE 2
+SOME LINE 3
+SOME LINE 4
+\stopmarkedlines
+
+\startmarkedlines[more]
+SOME MORE 1
+SOME MORE 2
+SOME MORE 3
+SOME MORE 4
+\stopmarkedlines
+
+\begingroup
+ \newlocalread\myreada
+ \immediate\openin\myreada {\markedfilename{test}}
+ \dostepwiserecurse{\lastmarkedline{test}}{\firstmarkedline{test}}{-1}{
+ \readline\myreada line #1 to \scratchstring #1 : \scratchstring \par
+ }
+ \immediate\closein\myreada
+\endgroup
+
+\blank
+
+\begingroup
+ \newlocalread\myreada
+ \immediate\openin\myreada {\markedfilename{more}}
+ \dostepwiserecurse{\firstmarkedline{more}}{\lastmarkedline{more}}{1}{
+ \read \myreada line #1 to \scratchstring #1 : \scratchstring \par
+ }
+ \immediate\closein\myreada
+\endgroup
+
+\stoptext
diff --git a/tex/context/modules/mkxl/m-timing.mkxl b/tex/context/modules/mkxl/m-timing.mkxl
new file mode 100644
index 000000000..3edfd14e2
--- /dev/null
+++ b/tex/context/modules/mkxl/m-timing.mkxl
@@ -0,0 +1,113 @@
+%D \module
+%D [ file=m-timing,
+%D version=2007.12.23,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Timing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Todo: adapt to latest metafun magic.
+
+\ifdefined\ShowNamedUsage \endinput \fi
+
+%D Written at the end of 2007, this module is dedicated to Taco. Reaching this
+%D point in \LUATEX\ was a non trivial effort. By visualizing a bit what happens
+%D when pages come out of \LUATEX, you may get an idea what is involved. It took
+%D much time an dedication to reach this point in the development. Add to that
+%D those daily Skype intense discussion, testing and debugging moments. Time flies
+%D but progress is impressive. The motto of this module could be: what you see
+%D is what you get. An there is much more to come \unknown.
+
+% \usemodule[timing]
+% \setupcolors[state=start]
+% \starttext
+% \dorecurse{200}{\input tufte \par} \ShowUsage{}
+% \stoptext
+
+\definecolor[usage:line] [darkred]
+\definecolor[usage:time] [darkblue]
+\definecolor[usage:frame][darkgray]
+
+\ctxloadluafile{trac-tim.lmt}
+
+\startluacode
+local progress = moduledata.progress
+
+function progress.show(filename,names,other)
+ if not filename or filename == "" then
+ filename = progress.defaultfilename or ""
+ end
+ for n, name in pairs(progress.names(filename)) do
+ if string.find(name,names) and name ~= other and name ~= "variables: lasttime" then
+ context.ShowNamedUsage(filename,name or "",other or "")
+ end
+ end
+end
+\stopluacode
+
+\startnotmode[no-timing]
+ \appendtoks\ctxlua{moduledata.progress.store()}\to\everystarttext
+ \appendtoks\ctxlua{moduledata.progress.store()}\to\everyshipout
+ \ctxlua{luatex.registerstopactions(function() moduledata.progress.save() end)}
+\stopnotmode
+
+\permanent\protected\def\ShowNamedUsage#1#2#3%
+ {\setbox\scratchbox\vbox\bgroup
+ \startMPcode{doublefun}
+ begingroup ; save p, q, b, h, w ;
+ path p, q, b ; numeric h, w ;
+ p := \cldcontext{moduledata.progress.path("#1","#2")} ;
+ % p := p shifted -llcorner p ;
+ if bbwidth(p) > 0 :
+ h := 100 ; w := 2 * h ;
+ w := \the\textwidth-3pt ; % correct for pen
+ p := p xstretched w ;
+ b := boundingbox (llcorner p -- llcorner p shifted (w,h)) ;
+ pickup pencircle scaled 3pt ; linecap := butt ;
+ draw b withcolor \MPcolor{usage:frame} ;
+ draw p withcolor \MPcolor{usage:line} ;
+ if ("#3" <> "") and ("#3" <> "#2") :
+ q := \cldcontext{moduledata.progress.path("#1","#3")} ;
+ % q := q shifted -llcorner q ;
+ if bbwidth(q) > 1 :
+ q := q xstretched w ;
+ pickup pencircle scaled 1.5pt ; linecap := butt ;
+ draw q withcolor \MPcolor{usage:time} ;
+ fi ;
+ fi ;
+ fi ;
+ endgroup ;
+ \stopMPcode
+ \egroup
+ \scratchdimen\wd\scratchbox
+ \ifdim\scratchdimen>\zeropoint
+ \startlinecorrection[blank]
+ \box\scratchbox \endgraf
+ \hbox to \scratchdimen\bgroup
+ \tttf\strut\detokenize{#2}\hss
+ \scratchcounter =\cldcontext{moduledata.progress.set("#1","\detokenize{#2}")}\relax
+ \scratchcounterone =\cldcontext{moduledata.progress.bot("#1","\detokenize{#2}")}\relax
+ \scratchcountertwo =\cldcontext{moduledata.progress.top("#1","\detokenize{#2}")}\relax
+ \scratchcounterthree=\numexpr\scratchcountertwo-\scratchcounterone\relax
+ \ifnum\scratchcounter >\zerocount set:\the\scratchcounter \quad\fi
+ \ifnum\scratchcounterthree>\zerocount inc:\the\scratchcounterthree\quad\fi
+ \ifnum\scratchcounterone >\zerocount min:\the\scratchcounterone \quad\fi
+ \ifnum\scratchcountertwo >\zerocount max:\the\scratchcountertwo \quad\fi
+ pages:\cldcontext{moduledata.progress.pages("#1")}%
+ \egroup
+ \stoplinecorrection
+ \fi}
+
+\permanent\protected\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}}
+\permanent\protected\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",".*", "variables: elapsed")}}
+\permanent\protected\def\ShowMemoryUsage #1{\ctxlua{moduledata.progress.show("#1","memory:.*","variables: elapsed")}}
+\permanent\protected\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1","nodes:.*", "variables: elapsed")}}
+\permanent\protected\def\ShowFilteredUsage#1#2{\ctxlua{moduledata.progress.show("#1","#2", "variables: elapsed")}}
+\permanent\protected\def\ShowSimpleUsage #1#2{\ctxlua{moduledata.progress.show("#1","#2")}}
+
+\endinput
diff --git a/tex/context/modules/mkxl/s-languages-goodies.lmt b/tex/context/modules/mkxl/s-languages-goodies.lmt
new file mode 100644
index 000000000..7256fd35d
--- /dev/null
+++ b/tex/context/modules/mkxl/s-languages-goodies.lmt
@@ -0,0 +1,99 @@
+if not modules then modules = { } end modules ['s-languages-goodies'] = {
+ version = 1.001,
+ comment = "companion to s-languages-goodies.mkxl",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+moduledata.languages = moduledata.languages or { }
+moduledata.languages.goodies = moduledata.languages.goodies or { }
+
+function moduledata.languages.goodies.show(specification)
+ specification = interfaces.checkedspecification(specification)
+ local filename = specification.file
+ if filename and filename ~= "" then
+ local list = table.load(resolvers.findfile(filename))
+ if list then
+ list = list.options
+ if list then
+ for i=1,#list do
+ local l = list[i]
+ local w = l.words
+ if w then
+ local pre = l.prefixes
+ local suf = l.suffixes
+ context.startsubject { title = table.concat(table.sortedkeys(l.patterns)," ") }
+ context(languages.strippedgoodiewords(w))
+ if pre then
+ context.blank()
+ context.bold("prefixes: ")
+ context(languages.strippedgoodiewords(pre))
+ end
+ if suf then
+ context.blank()
+ context.bold("suffixes: ")
+ context(languages.strippedgoodiewords(suf))
+ end
+ context.stopsubject()
+ end
+ end
+ end
+ end
+ end
+end
+
+local lpegmatch = lpeg.match
+
+moduledata.languages.goodies.ligaturehandlers = { }
+
+function moduledata.languages.goodies.ligatures(specification)
+
+ specification = interfaces.checkedspecification(specification)
+ local language = specification.language
+ local filename = specification.file
+
+ if not language then
+ elseif moduledata.languages.goodies.ligaturehandlers[language] then
+ else
+ -- fb ff ffb fff ffh ffi ffj ffk ffl fft fi fk fl ft
+ local list = specification.list or "ff fi fl ffi fff ffl"
+ local hash = table.tohash(lpeg.split(" ",list)) -- also strip
+ local pattern = (1-lpeg.utfchartabletopattern(hash))^1 * lpeg.P(-1)
+ local checked = { }
+
+ moduledata.languages.goodies.ligaturehandlers[language] = function(original)
+ if not checked[original] and not lpegmatch(pattern,original) then
+ checked[original] = true
+ end
+ return original
+ end
+
+ languages.installhandler(language,"moduledata.languages.goodies.ligaturehandlers." .. language .. "")
+
+ statistics.register(string.formatters["'% t' ligatures checked for language %a"](table.sortedkeys(hash), language), function()
+ return next(checked) and table.concat(table.sortedkeys(checked)," ") or nil
+ end)
+
+ local applied = languages.appliedoptions[language]
+
+ trackers.enable("languages.applied")
+
+ if applied then
+ statistics.register(string.formatters["options applied for language %a"](language), function()
+ return next(applied) and table.concat(table.sortedkeys(applied)," ") or nil
+ end)
+ statistics.register(string.formatters["missed ligatures for language %a"](language), function()
+ for k, v in next, applied do
+ checked[k] = nil
+ end
+ for k, v in next, hash do
+ checked[k] = nil
+ end
+ return next(checked) and table.concat(table.sortedkeys(checked)," ") or nil
+ end)
+ end
+
+ end
+
+end
diff --git a/tex/context/modules/mkxl/s-languages-goodies.mkxl b/tex/context/modules/mkxl/s-languages-goodies.mkxl
new file mode 100644
index 000000000..3ced071be
--- /dev/null
+++ b/tex/context/modules/mkxl/s-languages-goodies.mkxl
@@ -0,0 +1,144 @@
+%D \module
+%D [ file=s-languages-goodies,
+%D version=2021.25.03,
+%D title=\CONTEXT\ Style File,
+%D subtitle=Language Goodies,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startmodule[languages-goodies]
+
+\registerctxluafile{s-languages-goodies}{autosuffix}
+
+\installmodulecommandluasingle \showlanguagegoodies {moduledata.languages.goodies.show}
+\installmodulecommandluasingle \showlanguageligatures {moduledata.languages.goodies.ligatures}
+
+\stopmodule
+
+\continueifinputfile{s-languages-goodies.mkxl}
+
+% Beware, for now this file is a playground so what gets rendered
+% can differ per upload.
+
+\usemodule[art-01]
+
+% \setupbodyfont[libertine]
+
+\setuplanguage[de][goodies={lang-de.llg}]
+\setuplanguage[en][goodies={lang-en.llg}]
+
+\mainlanguage[de]
+
+% \setupalign[stretch,verytolerant,flushleft] \dontcomplain
+
+% \startlanguageoptions[de]
+% Zapf|innovation
+% \stoplanguageoptions
+
+% \tracinghyphenation3 \tracingonline2
+
+\starttext
+
+ \start
+% \setupalign[stretch,verytolerant,flushleft,nothyphenated] \dontcomplain
+
+% \showlanguageligatures[language=de,list=ff fi fl fk ft fb ffi ffl fff ffk fft ffb ffh ffj]
+% \showlanguageligatures[language=en,list=ff fi fl fk ft fb ffi ffl fff ffk fft ffb ffh ffj]
+
+% \starttitle[title={DE}]
+% \start \de \showlanguagegoodies [file={lang-de.llg}] \stop
+% \stoptitle
+
+% \starttitle[title={EN}]
+% \start \en \showlanguagegoodies[file={lang-en.llg}] \stop
+% \stoptitle
+
+ \page
+
+ \stop
+
+ % oeps effe
+ % nonexistentffitestcase
+ % nonexistentffltestcase
+
+ \enabletrackers[languages.goodies,languages.applied]
+
+ \start \de \dontcomplain
+
+% general
+
+% 0 : ignore
+% 1 : invisible % {}{}{}
+% 2 : no break % {}{}{}[9]
+% 3 : pre % {-}{}{}
+% 4 : pre replace % {-}{}{-}
+% 5 : post % {}{-}{}
+% 6 : post replace % {}{-}{-}
+% 7 : pre post % {-}{-}{}
+% 8 : pre post replace % {-}{-}{-}
+
+% \codedef\hccode
+% \codedef\hycode
+
+% \hccode"002D = "2010 \hycode"002D = "0 % hyphen minus
+% \hccode"00AD = "0000 \hycode"00AD = "1 % soft hyphen
+% \hccode"2010 = "2010 \hycode"2010 = "0 % hyphen
+% \hccode"2011 = "2010 \hycode"2011 = "2 % non breaking hyphen
+% \hccode"2012 = "2012 \hycode"2012 = "0 % figure dash
+% \hccode"2013 = "2013 \hycode"2013 = "0 % en dash
+% \hccode"2014 = "2014 \hycode"2014 = "0 % em dash
+
+
+% \permanent\protected\def\cwm{\discretionary preword postword{-}{}{-}}
+% \tracingonline2 \tracinghyphenation2
+
+% One can map to exhyphenchar and use a pre/post for that one but if
+% really needed \hbcode (before=pre) and \hacode (after=post) can be
+% introduced. Maybe only settable runtime via lua.
+
+\hccode"002D = "002D
+\hccode"2010 = "2010
+\hccode"2013 = "2013
+\hccode"2014 = "2014
+
+% Offline\cwm Anwendungen\par
+% {\hsize 1mm Offline\cwm Anwendungen\par}
+% Offline-Anwendungen\par
+% Offline{\char"2010}Anwendungen\par
+% {\hsize 1mm Offline-Anwendungen\par}
+% {\hsize 1mm Offline{\char"2010}Anwendungen\par}
+% {\hsize 1mm Offline{\endash}Anwendungen\par}
+% {\hsize 1mm Offline{\emdash}Anwendungen\par}
+ {\hsize 3mm \emdash Offline-Anwendungen\emdash\par}
+ {\hsize 3mm \emdash\wordboundary Offline-Anwendungen\wordboundary\emdash\par}
+ {\hsize 3mm \quotation{Offline-Anwendungen}\par}
+ {\hsize 3mm „Offline-Anwendungen“\par}
+ {\hsize 3mm -Offline-Anwendungen-\par}
+
+% OfflineAnwendungen\par
+% {\hsize 1mm OfflineAnwendungen\par}
+% Offline\par
+% {\hsize 1mm Offline\par}
+
+
+% \hyphenationmode\bitwiseflip\hyphenationmode-\forcehandlerhyphenationmodecode
+
+% \de \dontcomplain
+
+% \startexceptions[de]
+% multi-cul-ti{-}{}{-}word{-}{}{-}boun-daries
+% \stopexceptions
+
+% {multiculti-word-boundaries\par}
+% {multicultiwordboundaries\par}
+% {\hsize 1mm multicultiwordboundaries\par}
+% {\hsize 1mm multiculti-word-boundaries\par}
+% {\hsize 1mm multiwordboundaries\par}
+
+ \stop
+\stoptext
diff --git a/tex/context/modules/mkxl/s-system-macros.mkxl b/tex/context/modules/mkxl/s-system-macros.mkxl
new file mode 100644
index 000000000..605859000
--- /dev/null
+++ b/tex/context/modules/mkxl/s-system-macros.mkxl
@@ -0,0 +1,330 @@
+%D \module
+%D [ file=s-system-tokens.mkxl,
+%D version=2020.06.02,
+%D title=\CONTEXT\ Style File,
+%D subtitle=System Tokens Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This file is for Wolfgang and Hans and it's used in the transition from \MKIV\
+%D to the more robust \LMTX.
+
+% todo: \permanent\protected\let\select\directselect : same value (add ref)
+%
+% todo: when mutable, remove immutable, decide on how immutable it really is
+%
+% todo: just for the fun of it we can compare the table generated here to mkiv but it
+% needs the same hash exposure as we use in luametatex so i'll do that after all lmtx
+% macros are checked (maybe i need to backport some more but it has a low priority)
+%
+% todo: do we need something similar for lua functions etc (problem: performance hit)
+%
+% todo: and how about metapost ... i need a mp.hashtokens in order to do that and I also
+% need to think about protection there (tricky as we use an avl hash there)
+%
+% public undefined : SmallCaps scitebuffer sciteinlinebuffer
+% single todos : \ \- \\ \_
+
+\enablemode[texmacros]
+\enablemode[metapostmacros]
+% \enablemode[notmarked]
+\enablemode[everything]
+
+\startmodule[system-macros]
+
+\continueifinputfile{s-system-macros.mkxl}
+
+% \usemodule[article-basic] \setuplayout[tight] \setupbodyfont[7pt,tt]
+\usemodule[article-basic] \setuplayout[tight] \setupbodyfont[5pt,tt]
+
+\setupbackgrounds[page][background=color,backgroundcolor=darkgray] \setupcolors[textcolor=white]
+
+\setuppapersize
+ [A4,landscape]
+ [A4,landscape]
+
+\starttext
+
+\startluacode
+
+ if tex.modes.texmacros then
+
+ local context = context
+ local ctx_NC = context.NC
+ local ctx_NR = context.NR
+ local ctx_bold = context.bold
+ local ctx_verb = context.verbatim
+
+ local find = string.find
+ local gsub = string.gsub
+ local create = tokens.create
+
+ local crap = "[$>%|%&%#" .. string.char(0xEF) .. "]"
+
+ local basefile = resolvers.findfile("context.mkxl")
+ local swapnames = { }
+
+ local pattern = file.join(file.pathpart(basefile),"/*.mk*")
+ local filenames = dir.glob(pattern)
+ for i=1,#filenames do
+ swapnames[file.basename(filenames[i])] = true
+ end
+
+ local pattern = file.join(file.pathpart(basefile),"/*.l**")
+ local filenames = dir.glob(pattern)
+ for i=1,#filenames do
+ swapnames[file.basename(filenames[i])] = true
+ end
+
+ local hashnames = table.setmetatableindex(function(t,k)
+ local s = file.suffix(k)
+ local v = k
+ if s == "mkiv" then
+ local n = file.replacesuffix(k,"mkxl")
+ if swapnames[n] then
+ v = n
+ end
+ elseif s == "mkvi" then
+ local n = file.replacesuffix(k,"mklx")
+ if swapnames[n] then
+ v = n
+ end
+ elseif s == "lua" then
+ local n = file.replacesuffix(k,"lmt")
+ if swapnames[n] then
+ v = n
+ end
+ end
+ t[k] = v
+ return v
+ end)
+
+ require("mtx-interface")
+
+ local data = scripts.interface.editor("data")
+ local files = data and data.common and data.common.filenames or { }
+ local macros = { }
+ local flagged = 0
+ local total = 0
+ local list = tex.hashtokens()
+ local all = not tex.modes.notmarked
+ local everything = tex.modes.everything
+
+ local fmtname = resolvers.locateformat("cont-en.fmt")
+ if fmtname then
+ local logname = file.replacesuffix(fmtname,"log")
+ for filename in string.gmatch(io.loaddata(logname),"fullname=(%S+)") do
+ local s = file.suffix(filename)
+ local b = file.basename(filename)
+ if s ~= "lua" and s ~= "lmt" then
+ local d = io.loaddata(filename)
+ for m in string.gmatch(d,"\n[\\a-z]*[exg]*def\\([a-zA-Z_]+)") do
+ macros[m] = b
+ end
+ for m in string.gmatch(d,"\n[\\a-z]*[g]*let\\([a-zA-Z_]+)") do
+ macros[m] = b
+ end
+ end
+ end
+ end
+
+ table.sort(list)
+
+ local function show(visible, check)
+ -- context.starttabulate { "|l|l|l|lj2|l|l|l|l|l|l|l|l|" }
+ context.starttabulate { "|l|l|l|lj2|l|l|l|l|l|l|l|l|" }
+ for i=1,#list do
+ local k = list[i]
+ if check(k) then
+ local v = create(k)
+ local mutable = v.mutable and "mutable"
+ local immutable = v.immutable and "immutable"
+ local frozen = v.frozen and "frozen"
+ local permanent = v.permanent and "permanent"
+ local primitive = v.primitive and "primitive"
+ local instance = v.instance and "instance"
+ local dealtwith = mutable or immutable or mutable or frozen or permanent or primitive -- beware: we can have combinations
+ local whatever = find(k,"^[a-z][a-z][a-z]+_")
+ local cscommand = gsub(v.cmdname or "","_"," ")
+ local undefined = cscommand == "undefined cs"
+ local marked = (dealtwith and "+") or (whatever and "-") or (instance and "!")
+ if everything or ((all or not marked) and not find(k,"^[pvm]_") and not find(k,"^![tT]")) then
+ local parameters = v.parameters
+ local noaligned = v.noaligned and "noaligned"
+ local filename = files[k] or macros[k]
+ local csname = context.escape(k)
+ if undefined then
+ marked = "?"
+ end
+ ctx_NC() if marked then context(marked) end
+ ctx_NC() if primitive then ctx_bold(csname) else
+ ctx_verb(csname) end
+ ctx_NC() if parameters then context(parameters > 0 and parameters or "-") end
+ ctx_NC() if undefined then context.red(false) end
+ context(cscommand)
+ ctx_NC() if primitive then context(primitive) end
+ ctx_NC() if permanent then context(permanent) end
+ ctx_NC() if immutable then context(immutable) end
+ ctx_NC() if frozen then context(frozen) end
+ ctx_NC() if mutable then context(mutable) end
+ ctx_NC() if instance then context(instance) end
+ ctx_NC() if noaligned then context(noaligned) end
+ ctx_NC() if filename then context(hashnames[filename]) end
+ ctx_NC() ctx_NR()
+ end
+ if visible then
+ total = total + 1
+ if dealtwith then
+ flagged = flagged + 1
+ end
+ end
+ end
+ end
+ context.stoptabulate()
+ end
+
+ context.starttitle { title = "Public \\TEX\\ commands" }
+ show(true, function(k) return find(k,"^[a-zA-Z]+$") end)
+ context.stoptitle()
+
+ context.starttitle { title = "Private \\TEX\\ commands" }
+ show(false, function(k) return not find(k,"^[a-zA-Z]+$") and not find(k,crap) end)
+ context.stoptitle()
+
+ tokens.setters.macro("NumberOfVisible", total)
+ tokens.setters.macro("NumberOfFlagged", flagged)
+
+ end
+
+\stopluacode
+
+\startmode[texmacros]
+
+ \page
+
+ \starttabulate[|c|l|]
+ \HL
+ \NC \type {+} \NC mutable, immutable, frozen, permanent, primitive \NC \NR
+ \NC \type {-} \NC protected by obscurity (underscores) \NC \NR
+ \NC \type {!} \NC instance (can be frozen) \NC \NR
+ \NC \type {0-9} \NC the number of arguments (argument grabbing can be delegated) \NC \NR
+ \HL
+ \stoptabulate
+
+ \start \hsize 15cm \veryraggedright
+ Often frozen commands are redefined on demand and they can be overloaded. Mutable
+ doesn't mean that a user can change it without consequences, for instance the
+ \type {\current...} ones. Primitives come with the engine, permanent macros are
+ the core of \CONTEXT. Noaligned macros are special and dealt deep down when
+ scanning for alignment specific primitives.
+ \par \stop
+
+ \starttabulate[||r|]
+ \BC number of visible macros \NC \NumberOfVisible \NC \NR
+ \BC number of flagged macros \NC \NumberOfFlagged \NC \NR
+ \stoptabulate
+
+\stopmode
+
+\page
+
+\startluacode
+
+ if tex.modes.metapostmacros then
+
+ local context = context
+ -- local ctx_NC = context.NC
+ -- local ctx_NR = context.NR
+ -- local ctx_bold = context.bold
+
+ local find = string.find
+ local gsub = string.gsub
+ local create = tokens.create
+
+ context.starttitle { title = "\\METAFUN\\ commands" }
+
+ metapost.simple("prestine")
+
+ local mptotal = 0
+ local codes = metapost.codes
+ local types = metapost.types
+ local parameters = metapost.knownparameters
+ local procodes = mplib.propertycodes
+ local everything = tex.modes.everything
+
+ context.startcolumns { n = 5, distance = "1em" }
+ context.nohyphens(false)
+ context.obeyspaces(false)
+ local t = metapost.gethashentries("prestine",true) -- prestine:1
+ if t then
+ table.sort(t,function(a,b) return a[3] < b[3] end)
+ mptotal = #t
+ for i=1,mptotal do
+ local ti = t[i]
+ local code = codes[ti[1]]
+ local property = procodes[ti[2]]
+ local name = ti[3]
+ local vtype = ti[4]
+ local vardef = vtype and types[vtype] == "unsuffixedmacro"
+ context.bgroup()
+ -- context("%-15s\\quad",vardef and "(vardef) tag" or code)
+ context("%s %-15s\\quad",parameters[name] and "+" or "\\nbsp",vardef and "(vardef) tag" or code)
+ if property == "primitive" then
+ context.bf(false)
+ context.blue(false)
+ elseif property == "permanent" then
+ context.bf(false)
+ context.lightgreen(false)
+ elseif property == "immutable" then
+ context.bf(false)
+ context.lightcyan(false)
+ elseif property == "mutable" then
+ context.bf(false)
+ context.lightmagenta(false)
+ elseif everything or not find(name,"^%a+_") then
+ -- todo:
+ if vardef then
+ context.bf(false)
+ context.lightred(false)
+ end
+ end
+ context.verbatim(name)
+ context.egroup()
+ context.par()
+ end
+ end
+ context.stopcolumns()
+
+ context.stoptitle()
+
+ tokens.setters.macro("NumberOfMetafun", mptotal)
+
+ end
+\stopluacode
+
+\startmode [metapostmacros]
+
+ \page
+
+ \starttabulate[|c|l|]
+ \HL
+ \NC \type {-3} \NC \bf \lightmagenta mutable \NC \NR
+ \NC \type {1} \NC \bf \blue primitive \NC \NR
+ \NC \type {2} \NC \bf \lightgreen permanent \NC \NR
+ \NC \type {3} \NC \bf \lightcyan immutable \NC \NR
+ \NC \type {+} \NC \bf (also) used as key \NC \NR
+ \HL
+ \stoptabulate
+
+ \starttabulate[||r|]
+ \BC number of metafun entries \NC \NumberOfMetafun \NC \NR
+ \stoptabulate
+
+\stopmode
+
+\stopmodule
diff --git a/tex/context/modules/mkxl/s-system-tokens.mkxl b/tex/context/modules/mkxl/s-system-tokens.mkxl
new file mode 100644
index 000000000..b83a4f47b
--- /dev/null
+++ b/tex/context/modules/mkxl/s-system-tokens.mkxl
@@ -0,0 +1,84 @@
+%D \module
+%D [ file=s-system-tokens.mkxl,
+%D version=2020.06.02,
+%D title=\CONTEXT\ Style File,
+%D subtitle=System Tokens Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startmodule[system-tokens]
+
+\registerctxluafile{s-system-tokens}{}
+
+\permanent\protected\def\showsystemtokens{\ctxlua{moduledata.system.tokens.showlist()}} % can be public implementor
+
+\stopmodule
+
+\continueifinputfile{s-system-tokens.mkxl}
+
+\usemodule[article-basic]
+
+\setuppapersize[A4,landscape]
+
+\setuplayout[tight]
+
+\setupbodyfont[8pt]
+
+\starttext
+
+ \showsystemtokens
+
+ Some tokens cannot be created yet because they are more complex but eventually the creator will
+ deal with them. The indices are sometimes the same as internal but in most cases nicely start
+ at zero. When they start at another value, then there is an internal token or state that is not
+ user accessible. You always need to use symbolic constants as the numbers can change.
+
+ The first column is a classifier (which is experimental and categories might change when we feel
+ the need).
+
+ \startcolumns[n=5]
+ \starttabulate[|T||]
+ \NC 0 \NC unused \NC \NR
+ \NC 1 \NC regular \NC \NR
+ \NC 2 \NC character \NC \NR
+ \NC 3 \NC register \NC \NR
+ \NC 4 \NC internal \NC \NR
+ \NC 5 \NC reference \NC \NR
+ \NC 6 \NC data \NC \NR
+ \NC 7 \NC token \NC \NR
+ \NC 8 \NC node \NC \NR
+ \stoptabulate
+ \stopcolumns
+
+ \page
+
+ Here is a typeset table of \type {\startframed} using \type {\luatokentable\startframed}:
+
+ \luatokentable\startframed
+
+ which calls \type {\pack_framed_start_framed} where \type {\luatokentable\pack_framed_start_framed} gives:
+
+
+ \unprotect
+ \luatokentable\pack_framed_start_framed
+ \protect
+
+ So you can guess what generates this:
+
+ \unprotect
+ \luatokentable\pack_framed_start_framed_nop
+ \protect
+
+ And this:
+
+ \unprotect
+ \luatokentable\pack_framed_start_framed_yes
+ \protect
+
+\stoptext
+
diff --git a/tex/context/modules/mkxl/x-mathml.lmt b/tex/context/modules/mkxl/x-mathml.lmt
new file mode 100644
index 000000000..ba05c002e
--- /dev/null
+++ b/tex/context/modules/mkxl/x-mathml.lmt
@@ -0,0 +1,910 @@
+if not modules then modules = { } end modules ['x-mathml'] = {
+ version = 1.001,
+ comment = "companion to x-mathml.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This needs an upgrade to the latest greatest mechanisms. But ... it
+-- probably doesn't pay back as no mathml support ever did.
+
+local type, next = type, next
+local formatters, lower, find, gsub, match = string.formatters, string.lower, string.find, string.gsub, string.match
+local strip = string.strip
+local xmlsprint, xmlcprint, xmltext, xmlcontent, xmlempty = xml.sprint, xml.cprint, xml.text, xml.content, xml.empty
+local lxmlcollected, lxmlfilter = lxml.collected, lxml.filter
+local getid = lxml.getid
+local utfchar, utfcharacters, utfsplit, utflen = utf.char, utf.characters, utf.split, utf.len
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local P, Cs = lpeg.P, lpeg.Cs
+
+local mathml = { }
+moduledata.mathml = mathml
+lxml.mathml = mathml -- for the moment
+
+local context = context
+
+local ctx_enabledelimiter = context.enabledelimiter
+local ctx_disabledelimiter = context.disabledelimiter
+local ctx_xmlflush = context.xmlflush -- better xmlsprint
+
+local ctx_halign = context.halign
+local ctx_noalign = context.noalign
+local ctx_bgroup = context.bgroup
+local ctx_egroup = context.egroup
+local ctx_crcr = context.crcr
+
+local ctx_bTABLE = context.bTABLE
+local ctx_eTABLE = context.eTABLE
+local ctx_bTR = context.bTR
+local ctx_eTR = context.eTR
+local ctx_bTD = context.bTD
+local ctx_eTD = context.eTD
+
+local ctx_mn = context.mn
+local ctx_mi = context.mi
+local ctx_mo = context.mo
+local ctx_startimath = context.startimath
+local ctx_ignorespaces = context.ignorespaces
+local ctx_removeunwantedspaces = context.removeunwantedspaces
+local ctx_stopimath = context.stopimath
+
+local ctx_mmlapplycsymbol = context.mmlapplycsymbol
+
+local ctx_mathopnolimits = context.mathopnolimits
+local ctx_left = context.left
+local ctx_right = context.right
+
+-- an alternative is to remap to private codes, where we can have
+-- different properties .. to be done; this will move and become
+-- generic; we can then make the private ones active in math mode
+
+-- todo: handle opening/closing mo's here ... presentation mml is such a mess ...
+
+-- characters.registerentities()
+
+local doublebar = utfchar(0x2016)
+
+local n_replacements = {
+-- [" "] = utfchar(0x2002), -- "&textspace;" -> tricky, no &; in mkiv
+ ["."] = "{.}",
+ [","] = "{,}",
+ [" "] = "",
+}
+
+local l_replacements = { -- in main table
+ ["|"] = "\\mmlleftdelimiter\\vert",
+ ["{"] = "\\mmlleftdelimiter\\lbrace",
+ ["("] = "\\mmlleftdelimiter(",
+ ["["] = "\\mmlleftdelimiter[",
+ ["<"] = "\\mmlleftdelimiter<",
+ [doublebar] = "\\mmlleftdelimiter\\Vert",
+}
+local r_replacements = { -- in main table
+ ["|"] = "\\mmlrightdelimiter\\vert",
+ ["}"] = "\\mmlrightdelimiter\\rbrace",
+ [")"] = "\\mmlrightdelimiter)",
+ ["]"] = "\\mmlrightdelimiter]",
+ [">"] = "\\mmlrightdelimiter>",
+ [doublebar] = "\\mmlrightdelimiter\\Vert",
+}
+
+-- todo: play with asciimode and avoid mmlchar
+
+-- we can use the proper names now! todo
+
+local o_replacements = { -- in main table
+ ["@l"] = "\\mmlleftdelimiter.",
+ ["@r"] = "\\mmlrightdelimiter.",
+ ["{"] = "\\mmlleftdelimiter \\lbrace",
+ ["}"] = "\\mmlrightdelimiter\\rbrace",
+ ["|"] = "\\mmlleftorrightdelimiter\\vert",
+ -- ["."] = "\\mmlleftorrightdelimiter.",
+ ["/"] = "\\mmlleftorrightdelimiter\\solidus",
+ [doublebar] = "\\mmlleftorrightdelimiter\\Vert",
+ ["("] = "\\mmlleftdelimiter(",
+ [")"] = "\\mmlrightdelimiter)",
+ ["["] = "\\mmlleftdelimiter[",
+ ["]"] = "\\mmlrightdelimiter]",
+ -- ["<"] = "\\mmlleftdelimiter<",
+ -- [">"] = "\\mmlrightdelimiter>",
+ ["#"] = "\\mmlchar{35}",
+ ["$"] = "\\mmlchar{36}", -- $
+ ["%"] = "\\mmlchar{37}",
+ ["&"] = "\\mmlchar{38}",
+ ["^"] = "\\mmlchar{94}{}", -- strange, sometimes luatex math sees the char instead of \char so we
+ ["_"] = "\\mmlchar{95}{}", -- need the {} ... has to do with active mess feedback into scanner
+ ["~"] = "\\mmlchar{126}",
+ [" "] = "",
+ ["°"] = "^\\circ", -- hack
+
+ -- [utfchar(0xF103C)] = "\\mmlleftdelimiter<",
+ [utfchar(0xF1026)] = "\\mmlchar{38}",
+ [utfchar(0x02061)] = "", -- function applicator sometimes shows up in font
+ -- [utfchar(0xF103E)] = "\\mmlleftdelimiter>",
+ -- [utfchar(0x000AF)] = '\\mmlchar{"203E}', -- 0x203E
+}
+
+local simpleoperatorremapper = utf.remapper(o_replacements)
+
+--~ languages.data.labels.functions
+
+local i_replacements = {
+ ["sin"] = "\\sin",
+ ["cos"] = "\\cos",
+ ["abs"] = "\\abs",
+ ["arg"] = "\\arg",
+ ["codomain"] = "\\codomain",
+ ["curl"] = "\\curl",
+ ["determinant"] = "\\det",
+ ["divergence"] = "\\div",
+ ["domain"] = "\\domain",
+ ["gcd"] = "\\gcd",
+ ["grad"] = "\\grad",
+ ["identity"] = "\\id",
+ ["image"] = "\\image",
+ ["lcm"] = "\\lcm",
+ ["lim"] = "\\lim",
+ ["max"] = "\\max",
+ ["median"] = "\\median",
+ ["min"] = "\\min",
+ ["mode"] = "\\mode",
+ ["mod"] = "\\mod",
+ ["polar"] = "\\Polar",
+ ["exp"] = "\\exp",
+ ["ln"] = "\\ln",
+ ["log"] = "\\log",
+ ["sin"] = "\\sin",
+ ["arcsin"] = "\\arcsin",
+ ["sinh"] = "\\sinh",
+ ["arcsinh"] = "\\arcsinh",
+ ["cos"] = "\\cos",
+ ["arccos"] = "\\arccos",
+ ["cosh"] = "\\cosh",
+ ["arccosh"] = "\\arccosh",
+ ["tan"] = "\\tan",
+ ["arctan"] = "\\arctan",
+ ["tanh"] = "\\tanh",
+ ["arctanh"] = "\\arctanh",
+ ["cot"] = "\\cot",
+ ["arccot"] = "\\arccot",
+ ["coth"] = "\\coth",
+ ["arccoth"] = "\\arccoth",
+ ["csc"] = "\\csc",
+ ["arccsc"] = "\\arccsc",
+ ["csch"] = "\\csch",
+ ["arccsch"] = "\\arccsch",
+ ["sec"] = "\\sec",
+ ["arcsec"] = "\\arcsec",
+ ["sech"] = "\\sech",
+ ["arcsech"] = "\\arcsech",
+ [" "] = "",
+
+ ["false"] = "{\\mathrm false}",
+ ["notanumber"] = "{\\mathrm NaN}",
+ ["otherwise"] = "{\\mathrm otherwise}",
+ ["true"] = "{\\mathrm true}",
+ ["declare"] = "{\\mathrm declare}",
+ ["as"] = "{\\mathrm as}",
+
+}
+
+-- we could use a metatable or when accessing fallback on the
+-- key but at least we now have an overview
+
+local csymbols = {
+ arith1 = {
+ lcm = "lcm",
+ big_lcm = "lcm",
+ gcd = "gcd",
+ big_gcd = "big_gcd",
+ plus = "plus",
+ unary_minus = "minus",
+ minus = "minus",
+ times = "times",
+ divide = "divide",
+ power = "power",
+ abs = "abs",
+ root = "root",
+ sum = "sum",
+ product = "product",
+ },
+ fns = {
+ domain = "domain",
+ range = "codomain",
+ image = "image",
+ identity = "ident",
+ -- left_inverse = "",
+ -- right_inverse = "",
+ inverse = "inverse",
+ left_compose = "compose",
+ lambda = "labmda",
+ },
+ linalg1 = {
+ vectorproduct = "vectorproduct",
+ scalarproduct = "scalarproduct",
+ outerproduct = "outerproduct",
+ transpose = "transpose",
+ determinant = "determinant",
+ vector_selector = "selector",
+ -- matrix_selector = "matrix_selector",
+ },
+ logic1 = {
+ equivalent = "equivalent",
+ ["not"] = "not",
+ ["and"] = "and",
+ -- big_and = "",
+ ["xor"] = "xor",
+ -- big_xor = "",
+ ["or"] = "or",
+ -- big-or = "",
+ implies = "implies",
+ ["true"] = "true",
+ ["false"] = "false",
+ },
+ nums1 = {
+ -- based_integer = "based_integer"
+ rational = "rational",
+ inifinity = "infinity",
+ e = "expenonentiale",
+ i = "imaginaryi",
+ pi = "pi",
+ gamma = "gamma",
+ NaN = "NaN",
+ },
+ relation1 = {
+ eq = "eq",
+ lt = "lt",
+ gt = "gt",
+ neq = "neq",
+ leq = "leq",
+ geq = "geq",
+ approx = "approx",
+ },
+ set1 = {
+ cartesian_product = "cartesianproduct",
+ empty_set = "emptyset",
+ map = "map",
+ size = "card",
+ -- suchthat = "suchthat",
+ set = "set",
+ intersect = "intersect",
+ -- big_intersect = "",
+ union = "union",
+ -- big_union = "",
+ setdiff = "setdiff",
+ subset = "subset",
+ ["in"] = "in",
+ notin = "notin",
+ prsubset = "prsubset",
+ notsubset = "notsubset",
+ notprsubset = "notprsubset",
+ },
+ veccalc1 = {
+ divergence = "divergence",
+ grad = "grad",
+ curl = "curl",
+ laplacian = "laplacian",
+ Laplacian = "laplacian",
+ },
+ calculus1 = {
+ diff = "diff",
+ -- nthdiff = "",
+ partialdiff = "partialdiff",
+ int = "int",
+ -- defint = "defint",
+ },
+ integer1 = {
+ factorof = "factorof",
+ factorial = "factorial",
+ quotient = "quotient",
+ remainder = "rem",
+ },
+ linalg2 = {
+ vector = "vector",
+ matrix = "matrix",
+ matrixrow = "matrixrow",
+ },
+ mathmkeys = {
+ -- equiv = "",
+ -- contentequiv = "",
+ -- contentequiv_strict = "",
+ },
+ rounding1 = {
+ ceiling = "ceiling",
+ floor = "floor",
+ -- trunc = "trunc",
+ -- round = "round",
+ },
+ setname1 = {
+ P = "primes",
+ N = "naturalnumbers",
+ Z = "integers",
+ rationals = "rationals",
+ R = "reals",
+ complexes = "complexes",
+ },
+ complex1 = {
+ -- complex_cartesian = "complex_cartesian", -- ci ?
+ real = "real",
+ imaginary = "imaginary",
+ -- complex_polar = "complex_polar", -- ci ?
+ argument = "arg",
+ conjugate = "conjugate",
+ },
+ interval1 = { -- not an apply
+ -- integer_interval = "integer_interval",
+ interval = "interval",
+ interval_oo = { tag = "interval", closure = "open" },
+ interval_cc = { tag = "interval", closure = "closed" },
+ interval_oc = { tag = "interval", closure = "open-closed" },
+ interval_co = { tag = "interval", closure = "closed-open" },
+ },
+ linalg3 = {
+ -- vector = "vector.column",
+ -- matrixcolumn = "matrixcolumn",
+ -- matrix = "matrix.column",
+ },
+ minmax1 = {
+ min = "min",
+ -- big_min = "",
+ max = "max",
+ -- big_max = "",
+ },
+ piece1 = {
+ piecewise = "piecewise",
+ piece = "piece",
+ otherwise = "otherwise",
+ },
+ error1 = {
+ -- unhandled_symbol = "",
+ -- unexpected_symbol = "",
+ -- unsupported_CD = "",
+ },
+ limit1 = {
+ -- limit = "limit",
+ -- both_sides = "both_sides",
+ -- above = "above",
+ -- below = "below",
+ -- null = "null",
+ tendsto = "tendsto",
+ },
+ list1 = {
+ -- map = "",
+ -- suchthat = "",
+ -- list = "list",
+ },
+ multiset1 = {
+ size = { tag = "card", type = "multiset" },
+ cartesian_product = { tag = "cartesianproduct", type = "multiset" },
+ empty_set = { tag = "emptyset", type = "multiset" },
+ -- multi_set = { tag = "multiset", type = "multiset" },
+ intersect = { tag = "intersect", type = "multiset" },
+ -- big_intersect = "",
+ union = { tag = "union", type = "multiset" },
+ -- big_union = "",
+ setdiff = { tag = "setdiff", type = "multiset" },
+ subset = { tag = "subset", type = "multiset" },
+ ["in"] = { tag = "in", type = "multiset" },
+ notin = { tag = "notin", type = "multiset" },
+ prsubset = { tag = "prsubset", type = "multiset" },
+ notsubset = { tag = "notsubset", type = "multiset" },
+ notprsubset = { tag = "notprsubset", type = "multiset" },
+ },
+ quant1 = {
+ forall = "forall",
+ exists = "exists",
+ },
+ s_dist = {
+ -- mean = "mean.dist",
+ -- sdev = "sdev.dist",
+ -- variance = "variance.dist",
+ -- moment = "moment.dist",
+ },
+ s_data = {
+ mean = "mean",
+ sdev = "sdev",
+ variance = "vriance",
+ mode = "mode",
+ median = "median",
+ moment = "moment",
+ },
+ transc1 = {
+ log = "log",
+ ln = "ln",
+ exp = "exp",
+ sin = "sin",
+ cos = "cos",
+ tan = "tan",
+ sec = "sec",
+ csc = "csc",
+ cot = "cot",
+ sinh = "sinh",
+ cosh = "cosh",
+ tanh = "tanh",
+ sech = "sech",
+ csch = "cscs",
+ coth = "coth",
+ arcsin = "arcsin",
+ arccos = "arccos",
+ arctan = "arctan",
+ arcsec = "arcsec",
+ arcscs = "arccsc",
+ arccot = "arccot",
+ arcsinh = "arcsinh",
+ arccosh = "arccosh",
+ arctanh = "arstanh",
+ arcsech = "arcsech",
+ arccsch = "arccsch",
+ arccoth = "arccoth",
+ },
+}
+
+function xml.functions.remapmmlcsymbol(e)
+ local at = e.at
+ local cd = at.cd
+ if cd then
+ cd = csymbols[cd]
+ if cd then
+ local tx = e.dt[1]
+ if tx and tx ~= "" then
+ local tg = cd[tx]
+ if tg then
+ at.cd = nil
+ at.cdbase = nil
+ e.dt = { }
+ if type(tg) == "table" then
+ for k, v in next, tg do
+ if k == "tag" then
+ e.tg = v
+ else
+ at[k] = v
+ end
+ end
+ else
+ e.tg = tg
+ end
+ end
+ end
+ end
+ end
+end
+
+function xml.functions.remapmmlbind(e)
+ e.tg = "apply"
+end
+
+function xml.functions.remapopenmath(e)
+ local tg = e.tg
+ if tg == "OMOBJ" then
+ e.tg = "math"
+ elseif tg == "OMA" then
+ e.tg = "apply"
+ elseif tg == "OMB" then
+ e.tg = "apply"
+ elseif tg == "OMS" then
+ local at = e.at
+ e.tg = "csymbol"
+ e.dt = { at.name or "unknown" }
+ at.name = nil
+ elseif tg == "OMV" then
+ local at = e.at
+ e.tg = "ci"
+ e.dt = { at.name or "unknown" }
+ at.name = nil
+ elseif tg == "OMI" then
+ e.tg = "ci"
+ end
+ e.rn = "mml"
+end
+
+function mathml.checked_operator(str)
+ context(simpleoperatorremapper(str))
+end
+
+function mathml.stripped(str)
+ context(strip(str))
+end
+
+local p_entity = (P("&") * ((1-P(";"))^0) * P(";"))
+local p_utfchar = lpegpatterns.utf8character
+local p_spacing = lpegpatterns.whitespace^1
+
+local p_mn = Cs((p_entity/"" + p_spacing/utfchar(0x205F) + p_utfchar/n_replacements)^0)
+local p_strip = Cs((p_entity/"" + p_utfchar )^0)
+local p_mi = Cs((p_entity/"" + p_utfchar/i_replacements)^0)
+
+function mathml.mn(id)
+ -- maybe at some point we need to interpret the number, but
+ -- currently we assume an upright font
+ ctx_mn(lpegmatch(p_mn,xmlcontent(getid(id)) or ""))
+end
+
+function mathml.mo(id)
+ local str = lpegmatch(p_strip,xmlcontent(getid(id)) or "")
+ context(simpleoperatorremapper(str) or str)
+end
+
+function mathml.mi(id)
+ -- we need to strip comments etc .. todo when reading in tree
+ local e = getid(id)
+ local str = e.dt
+ if type(str) == "table" then
+ local n = #str
+ if n == 0 then
+ -- nothing to do
+ elseif n == 1 then
+ local first = str[1]
+ if type(first) == "string" then
+ -- local str = gsub(first,"&.-;","") -- bah
+ -- local rep = i_replacements[str]
+ -- if not rep then
+ -- rep = gsub(str,".",i_replacements)
+ -- end
+ local str = lpegmatch(p_strip,first)
+ local rep = i_replacements[str] or lpegmatch(p_mi,str)
+ context(rep)
+ -- ctx_mi(rep)
+ else
+ ctx_xmlflush(id) -- xmlsprint or so
+ end
+ else
+ ctx_xmlflush(id) -- xmlsprint or so
+ end
+ else
+ ctx_xmlflush(id) -- xmlsprint or so
+ end
+end
+
+function mathml.mfenced(id) -- multiple separators
+ id = getid(id)
+ local at = id.at
+ local left = at.open or "("
+ local right = at.close or ")"
+ local separators = at.separators or ","
+ local l = l_replacements[left]
+ local r = r_replacements[right]
+ ctx_enabledelimiter()
+ if l then
+ context(l_replacements[left] or o_replacements[left] or "")
+ else
+ context(o_replacements["@l"])
+ context(left)
+ end
+ ctx_disabledelimiter()
+ local collected = lxmlfilter(id,"/*") -- check the *
+ if collected then
+ local n = #collected
+ if n == 0 then
+ -- skip
+ elseif n == 1 then
+ xmlsprint(collected[1]) -- to be checked
+ else
+ local t = utfsplit(separators,true)
+ for i=1,n do
+ xmlsprint(collected[i]) -- to be checked
+ if i < n then
+ local m = t[i] or t[#t] or ""
+ if m == "|" then
+ m = "\\enabledelimiter\\middle|\\relax\\disabledelimiter"
+ elseif m == doublebar then
+ m = "\\enabledelimiter\\middle|\\relax\\disabledelimiter"
+ elseif m == "{" then
+ m = "\\{"
+ elseif m == "}" then
+ m = "\\}"
+ end
+ context(m)
+ end
+ end
+ end
+ end
+ ctx_enabledelimiter()
+ if r then
+ context(r_replacements[right] or o_replacements[right] or "")
+ else
+ context(right)
+ context(o_replacements["@r"])
+ end
+ ctx_disabledelimiter()
+end
+
+local function flush(e,tag,toggle)
+ if tag == "none" then
+ -- if not toggle then
+ context("{}") -- {} starts a new ^_ set
+ -- end
+ elseif toggle then
+ context("^{")
+ xmlsprint(e.dt)
+ context("}{}") -- {} starts a new ^_ set
+ else
+ context("_{")
+ xmlsprint(e.dt)
+ context("}")
+ end
+ return not toggle
+end
+
+function mathml.mmultiscripts(id)
+ local done, toggle = false, false
+ for e in lxmlcollected(id,"/*") do
+ local tag = e.tg
+ if tag == "mprescripts" then
+ context("{}")
+ done = true
+ elseif done then
+ toggle = flush(e,tag,toggle)
+ end
+ end
+ local done, toggle = false, false
+ for e in lxmlcollected(id,"/*") do
+ local tag = e.tg
+ if tag == "mprescripts" then
+ break
+ elseif done then
+ toggle = flush(e,tag,toggle)
+ else
+ xmlsprint(e)
+ done = true
+ end
+ end
+end
+
+local columnalignments = {
+ left = "flushleft",
+ right = "flushright",
+ center = "middle",
+}
+
+local rowalignments = {
+ top = "high",
+ bottom = "low",
+ center = "lohi",
+ baseline = "top",
+ axis = "lohi",
+}
+
+local frametypes = {
+ none = "off",
+ solid = "on",
+ dashed = "on",
+}
+
+-- crazy element ... should be a proper structure instead of such a mess
+
+function mathml.mcolumn(root)
+ root = getid(root)
+ local matrix, numbers = { }, 0
+ local function collect(m,e)
+ local tag = e.tg
+ if tag == "mi" or tag == "mn" or tag == "mo" or tag == "mtext" then
+ local str = xmltext(e)
+ str = lpegmatch(p_strip,str)
+ for s in utfcharacters(str) do
+ m[#m+1] = { tag, s }
+ end
+ if tag == "mn" then
+ local n = utflen(str)
+ if n > numbers then
+ numbers = n
+ end
+ end
+ elseif tag == "mspace" or tag == "mline" then
+ local str = e.at.spacing or ""
+ for s in utfcharacters(str) do
+ m[#m+1] = { tag, s }
+ end
+ -- elseif tag == "mline" then
+ -- m[#m+1] = { tag, e }
+ end
+ end
+ for e in lxmlcollected(root,"/*") do
+ local m = { }
+ matrix[#matrix+1] = m
+ if e.tg == "mrow" then
+ -- only one level
+ for e in lxmlcollected(e,"/*") do
+ collect(m,e)
+ end
+ else
+ collect(m,e)
+ end
+ end
+ ctx_halign()
+ ctx_bgroup()
+ context([[\hss\startimath\alignmark\stopimath\aligntab\startimath\alignmark\stopimath\cr]])
+ for i=1,#matrix do
+ local m = matrix[i]
+ local mline = true
+ for j=1,#m do
+ if m[j][1] ~= "mline" then
+ mline = false
+ break
+ end
+ end
+ if mline then
+ ctx_noalign([[\obeydepth\nointerlineskip]])
+ end
+ for j=1,#m do
+ local mm = m[j]
+ local tag, chr = mm[1], mm[2]
+ if tag == "mline" then
+ -- This code is under construction ... I need some real motivation
+ -- to deal with this kind of crap.
+--~ local n, p = true, true
+--~ for c=1,#matrix do
+--~ local mc = matrix[c][j]
+--~ if mc then
+--~ mc = mc[2]
+--~ if type(mc) ~= "string" then
+--~ n, p = false, false
+--~ break
+--~ elseif find(mc,"^[%d ]$") then -- rangecheck is faster
+--~ -- digit
+--~ elseif not find(mc,"^[%.%,]$") then -- rangecheck is faster
+--~ -- punctuation
+--~ else
+--~ n = false
+--~ break
+--~ end
+--~ end
+--~ end
+--~ if n then
+--~ chr = "\\mmlmcolumndigitrule"
+--~ elseif p then
+--~ chr = "\\mmlmcolumnpunctuationrule"
+--~ else
+--~ chr = "\\mmlmcolumnsymbolrule" -- should be widest char
+--~ end
+ chr = "\\hrulefill"
+ elseif tag == "mspace" then
+ chr = "\\mmlmcolumndigitspace" -- utfchar(0x2007)
+ end
+ if j == numbers + 1 then
+ context("\\aligntab")
+ end
+ local nchr = n_replacements[chr]
+ context(nchr or chr)
+ end
+ ctx_crcr()
+ end
+ ctx_egroup()
+end
+
+local spacesplitter = lpeg.tsplitat(" ")
+
+function mathml.mtable(root)
+ -- todo: align, rowspacing, columnspacing, rowlines, columnlines
+ root = getid(root)
+ local at = root.at
+ local rowalign = at.rowalign
+ local columnalign = at.columnalign
+ local frame = at.frame
+ local rowaligns = rowalign and lpegmatch(spacesplitter,rowalign)
+ local columnaligns = columnalign and lpegmatch(spacesplitter,columnalign)
+ local frames = frame and lpegmatch(spacesplitter,frame)
+ local framespacing = at.framespacing or "0pt"
+ local framespacing = at.framespacing or "-\\ruledlinewidth" -- make this an option
+
+ ctx_bTABLE { frame = frametypes[frame or "none"] or "off", offset = framespacing, background = "" } -- todo: use xtables and definextable
+ for e in lxmlcollected(root,"/(mml:mtr|mml:mlabeledtr)") do
+ ctx_bTR()
+ local at = e.at
+ local col = 0
+ local rfr = at.frame or (frames and frames [#frames])
+ local rra = at.rowalign or (rowaligns and rowaligns [#rowaligns])
+ local rca = at.columnalign or (columnaligns and columnaligns[#columnaligns])
+ local ignorelabel = e.tg == "mlabeledtr"
+ for e in lxmlcollected(e,"/mml:mtd") do -- nested we can use xml.collected
+ col = col + 1
+ if ignorelabel and col == 1 then
+ -- get rid of label, should happen at the document level
+ else
+ local at = e.at
+ local rowspan = at.rowspan or 1
+ local columnspan = at.columnspan or 1
+ local cra = rowalignments [at.rowalign or (rowaligns and rowaligns [col]) or rra or "center"] or "lohi"
+ local cca = columnalignments[at.columnalign or (columnaligns and columnaligns[col]) or rca or "center"] or "middle"
+ local cfr = frametypes [at.frame or (frames and frames [col]) or rfr or "none" ] or "off"
+ ctx_bTD { align = formatters["{%s,%s}"](cra,cca), frame = cfr, nx = columnspan, ny = rowspan }
+ if xmlempty(e,".") then
+ -- nothing, else hsize max
+ else
+ ctx_startimath()
+ -- ctx_ignorespaces()
+ xmlcprint(e)
+ -- ctx_removeunwantedspaces()
+ ctx_stopimath()
+ end
+ ctx_eTD()
+ end
+ end
+ -- if e.tg == "mlabeledtr" then
+ -- ctx_bTD()
+ -- xmlcprint(xml.first(e,"/!mml:mtd"))
+ -- ctx_eTD()
+ -- end
+ ctx_eTR()
+ end
+ ctx_eTABLE()
+end
+
+function mathml.csymbol(root)
+ root = getid(root)
+ local at = root.at
+ local encoding = at.encoding or ""
+ local hash = url.hashed(lower(at.definitionUrl or ""))
+ local full = hash.original or ""
+ local base = hash.path or ""
+ local text = strip(xmltext(root) or "")
+ ctx_mmlapplycsymbol(full,base,encoding,text)
+end
+
+local p = lpeg.Cs(((1-lpegpatterns.whitespace)^1 / "mml:enclose:%0" + (lpegpatterns.whitespace^1)/",")^1)
+
+function mathml.menclosepattern(root)
+ root = getid(root)
+ local a = root.at.notation
+ if a and a ~= "" then
+ context(lpegmatch(p,a))
+ end
+end
+
+function xml.is_element(e,name)
+ return type(e) == "table" and (not name or e.tg == name)
+end
+
+function mathml.cpolar_a(root)
+ root = getid(root)
+ local dt = root.dt
+ ctx_mathopnolimits("Polar")
+ ctx_left(false,"(")
+ for k=1,#dt do
+ local dk = dt[k]
+ if xml.is_element(dk,"sep") then
+ context(",")
+ else
+ xmlsprint(dk)
+ end
+ end
+ ctx_right(false,")")
+end
+
+-- crap .. maybe in char-def a mathml overload
+
+local mathmleq = {
+ [utfchar(0x00AF)] = utfchar(0x203E),
+}
+
+function mathml.extensible(chr)
+ context(mathmleq[chr] or chr)
+end
+
+--
+
+local function install(name,action)
+ interfaces.implement {
+ name = name,
+ public = true,
+ -- protected = true, -- some definitely not !
+ arguments = "argument",
+ actions = action,
+ }
+end
+
+install("mathml_mi", mathml.mi)
+install("mathml_mo", mathml.mo)
+install("mathml_mn", mathml.mn)
+install("mathml_mfenced", mathml.mfenced)
+install("mathml_mmultiscripts", mathml.mmultiscripts)
+install("mathml_menclosepattern", mathml.menclosepattern)
+install("mathml_mtable", mathml.mtable)
+install("mathml_mcolumn", mathml.mcolumn)
+install("mathml_extensible", mathml.extensible)
+
+install("mathml_csymbol", mathml.csymbol)
+install("mathml_cpolar_a", mathml.cpolar_a)
+
+install("mathml_cpolar_extensible", mathml.cpolar_extensible)
diff --git a/tex/context/modules/mkxl/x-mathml.mkxl b/tex/context/modules/mkxl/x-mathml.mkxl
new file mode 100644
index 000000000..fbfc17883
--- /dev/null
+++ b/tex/context/modules/mkxl/x-mathml.mkxl
@@ -0,0 +1,2448 @@
+%D \module
+%D [ file=x-mathml,
+%D version=2008.05.29, (evolved from pre 2000 code)
+%D title=\CONTEXT\ XML Modules,
+%D subtitle=\MATHML,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% \xmlfilter{#1}{/*/name()} -> \xmltag
+
+% This implementation looks like a hack ... this is because we deal with all weird
+% cases we ran into, including abuse that was supposed to render ok (even if it
+% didn't in other renderers) .. it was simply expected to work that way. It is also
+% the product of stepwise adaptation to what we run into. And that in turn is often
+% determined by the tools that were used to produce the \XML. Even worse is the
+% cycling between coding that happens in projects: from content\ \MATHML\ to
+% OpenMath to asciimath to presentation \MATHML\ to \unknown\ which all depends on
+% what tools are available to render in a browser (where first \MATHML\ was hardly
+% supported, then became accepted, then was taken over by mathjax, then merged with
+% other input methods and who knopws what comes next in these days where technologies
+% are shortlived and the next best thing is already waiting around the corner.
+%
+% So, consider this module to be under constant construction and clean up. We still
+% use a funny mix of xml, tex and lua. I could rewrite the lot but it also shows
+% how context evolves. I might end up with a lua-only implementation some day, but
+% I must find a real good reason to spend time on it as so far it never paid back.
+% As far as I can tell, publishers have never shown much (real) interest anyway or
+% at least I haven't met one who cared to invest in it. If they run into \MATHML\
+% they just expect it to be supported.
+%
+% This variant is adapted to \LMTX\ and might evolve with upcoming variations of
+% the standard. As with \SVG\ and probably other \XML\ definitions that target a
+% specific domain, \MATHML\ is now more just something for browsers and \HTML\
+% usage (although support fluctuates). It's getting less generic (or at least we
+% see no more structural elements showing up) and with \CSS\ becoming the
+% recomended way to control local optimizations it indeed looks like only browsers
+% are the target, unless we can just ignore all that. Limitations of renderers,
+% specific usage, application determined \XML\ ... where will it end. All we can do
+% is follow and try to keep up, but maybe the more web it becomes, the less \TEX\
+% users need to care (read: can stick to \TEX\ coding).
+%
+% See the \MKII\ and \MKIV\ files for a history and the hacks we had to use in
+% the past.
+
+\writestatus{loading}{ConTeXt XML Macros / MathML Renderer}
+
+\unprotect
+
+\usemodule[x][calcmath]
+%usemodule[x][asciimath]
+
+\startmodule [mathml]
+
+\registerctxluafile{x-mathml}{autosuffix}
+
+\setupxml[\c!entities=\v!yes] % load big entities table
+
+\def\ctxmodulemathml#1{\ctxlua{moduledata.mathml.#1}}
+
+\startxmlsetups xml:mml:define
+ \xmlsetsetup{#1} {(formula|subformula)} {mml:formula}
+ \xmlfilter {#1} {omt:*/function(remapopenmath)}
+ \xmlfilter {#1} {mml:bind/function(remapmmlbind)}
+ \xmlfilter {#1} {mml:csymbol/function(remapmmlcsymbol)}
+ \xmlsetsetup{#1} {mml:*} {mml:*}
+ \xmlsetsetup{#1} {mml:apply/mml:apply/mml:inverse/../..} {mml:apply:inverse}
+ \xmlstrip {#1} {(mml:mi|mml:mo|mml:mn|mml:csymbol)}
+\stopxmlsetups
+
+\xmlregisterns{omt}{openmath}
+\xmlregisterns{mml}{mathml}
+
+\xmlregistersetup{xml:mml:define}
+
+\xmlmapvalue {mml:math:mode} {display} {\displaymathematics} % we had this already
+\xmlmapvalue {mml:math:mode} {inline} {\inlinemathematics }
+
+\xmlmapvalue {mml:math:display} {block} {\displaymathematics} % before this showed up
+\xmlmapvalue {mml:math:display} {inline} {\inlinemathematics }
+
+\xmlmapvalue {mml:math:dir} {ltr} {\setfalse\c_math_right_to_left\math_basics_synchronize_direction}
+\xmlmapvalue {mml:math:dir} {rtl} {\settrue \c_math_right_to_left\math_basics_synchronize_direction}
+
+\edef\mmlconstantone {1}
+\edef\mmlconstantfalse{false}
+
+\startxmlsetups mml:math
+ \begingroup
+ \enableautofences
+ \enableautofencemode
+ \xmlval {mml:math:dir} {\xmlatt{#1}{dir}} {}
+ \xmlval {mml:math:display} {\xmlatt{#1}{display}} {
+ \xmlval {mml:math:mode} {\xmlatt{#1}{mode}} {
+ \automathematics
+ }
+ }
+ {
+ \xmlflush{#1}
+ }
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:imath
+ \inlinemathematics {
+ \enableautofences
+ \enableautofencemode
+ \xmlflush{#1}
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:dmath
+ \displaymathematics {
+ \enableautofences
+ \enableautofencemode
+ \xmlflush{#1}
+ }
+\stopxmlsetups
+
+%D First we define some general formula elements.
+
+\startxmlsetups mml:formula
+ \edef\mmlformulaid {\xmlatt{#1}{id}}
+ \edef\mmlformulalabel {\xmlatt{#1}{label}\mmlformulaid}
+ \edef\mmlformulasublabel{\xmlatt{#1}{sublabel}\mmlformulaid}
+ \doifsomething\mmlformulalabel{\placeformula[\mmlformulalabel]{\mmlformulasublabel}}
+ \startformula
+ \xmlfirst{#1}{/mml:math}
+ \stopformula
+\stopxmlsetups
+
+
+\setfalse\mmlignoredelimiter % alternatively we could turn it on/off inside the start/stop and ignore \left\right\middle otherwise
+
+\let\mmlleftdelimiter \autofenceopen
+\let\mmlmiddledelimiter \autofencemiddle
+\let\mmlrightdelimiter \autofenceclose
+\let\mmlleftorrightdelimiter\autofenceboth
+
+\def\mmlchar#1{\char#1 } % used in lua code
+
+%D The rendering macros:
+
+\def\MMLrm{\mr}
+
+\def\MMLseparator#1{\removeunwantedspaces{#1}\ignorespaces} % nils space after separator
+\def\MMLseparator#1{,} % todo, for europe we need to block the space
+
+%D Since I only had the draft of MathML 2 and later 3 as example of rendering, there
+%D are probably a lot of omissions and misinterpretations. At least I learned some
+%D bits and pieces of math rendering.
+%D
+%D The main complications were not so much the math, but to find the most efficient
+%D way to handle elements without spacing beging messed up. The first implementation
+%D was aimed at getting reasonable output, this second implementation is already
+%D better in terms of handling nesting, and I will definitely need a third one that
+%D has more efficient and less ugly code.
+%D
+%D The \TEX\ part is not that complicated and once the preprocessor was okay, the
+%D rest way just a lot of keying and testing. It all comes down to gobbling,
+%D redefining, and not so much to parsing.
+%D
+%D The second implementation expanded the whole math sequence into an internal \TEX\
+%D representation. This is a rather clean and fast process. Filtering and testing
+%D takes place by redefining the internal representation macros.
+%D
+%D The third implementation may look a bit more messy in some respects. This is
+%D because in \TEX\ it's not that trivial to implement a tree handler. We use a
+%D stack for the \type {apply} element and other sequential content. Occasionally we
+%D need to peek into child elements which involves messy code. This implementation
+%D is closer to the normal \XML\ handling in \CONTEXT.
+%D
+%D This fourth variant just improves on the third. It uses some tricks available in
+%D \LUAMETATEX\ where we have extended the math machinery.
+
+%D We start with the parent elements and the option handler.
+
+\protected\def\xmlmathmldirective#1{\dosetvalue{MML#1}}
+
+\xmlinstalldirective{mathml}{xmlmathmldirective}
+
+%D In the styles, options can be set with:
+
+\protected\def\setupMMLappearance[#1]{\dodoubleargument\getparameters[MML#1]} % no @@ because passed to lua
+
+%D We will apply inner math to all bits and pieces made up by an \type {apply}.
+
+\def\MMLmathinner
+ {\ifinner
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\mathinner
+ \fi}
+
+%D Auxiliary MathML macros: (to be generalized)
+
+\def\mmlfirst #1{\xmlelement{#1}{1}} % we can move these inline if needed
+\def\mmlsecond #1{\xmlelement{#1}{2}}
+\def\mmlthird #1{\xmlelement{#1}{3}}
+\def\mmlprelast#1{\xmlelement{#1}{-2}}
+\def\mmllast #1{\xmlelement{#1}{-1}}
+
+\starttexdefinition doifelsemmlfunction #1
+ \xmldoifelse {#1} {/mml:fn} {
+ \firstoftwoarguments
+ } {
+ \xmldoifelse {#1} {/mml:apply/mml:fn} {
+ \firstoftwoarguments
+ } {
+ \xmldoifelse {#1} {/mml:ci[@type=='fn']} {
+ \firstoftwoarguments
+ } {
+ \secondoftwoarguments
+ }
+ }
+ }
+\stoptexdefinition
+
+%D A couple of lists:
+
+\convertargument
+ mml:times|mml:divide|mml:power|%
+ mml:lt|mml:gt|mml:eq|mml:leq|mml:geq|%
+ mml:in|mml:inverse|%
+ mml:fn|%
+ mml:floor|mml:ceiling|%
+ mml:mean|%
+ mml:selector|%
+ mml:abs|mml:int|mml:limit|mml:sum|mml:product|%
+ mml:outerproduct|mml:innerproduct|mml:scalarproduct%
+\to \MMLcmainresetlist
+
+\convertargument
+ mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|%
+ mml:cos|mml:arccos|mml:cosh|mml:arccosh|%
+ mml:tan|mml:arctan|mml:tanh|mml:arctanh|%
+ mml:cot|mml:arccot|mml:coth|mml:arccoth|%
+ mml:csc|mml:arccsc|mml:csch|mml:arccsch|%
+ mml:sec|mml:arcsec|mml:sech|mml:arcsech|%
+ mml:ln|mml:exp|mml:log|%
+ mml:abs|mml:int|mml:limit|mml:sum|mml:product|%
+ mml:fn%
+\to \MMLcfunctionlist
+
+\convertargument
+ mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|%
+ mml:cos|mml:arccos|mml:cosh|mml:arccosh|%
+ mml:tan|mml:arctan|mml:tanh|mml:arctanh|%
+ mml:cot|mml:arccot|mml:coth|mml:arccoth|%
+ mml:csc|mml:arccsc|mml:csch|mml:arccsch|%
+ mml:sec|mml:arcsec|mml:sech|mml:arcsech|%
+ mml:ln|mml:exp|mml:log|%
+ mml:abs%
+\to \MMLcpurefunctionlist
+
+\convertargument
+ mml:diff|mml:partialdiff|mml:root%
+\to \MMLcconstructlist
+
+%D We use inner and grouping (begin/end and no b/e) else we get problems with
+%D 1/2(1+2) and alike. The problem with apply is that we need to take care of
+%D several situations, like:
+%D
+%D \starttyping
+%D <apply> <.../> ...
+%D <apply> <fn> ...
+%D <apply> <apply> <ci> ...
+%D <apply> <apply> <fn> <ci> ...
+%D \stoptyping
+%D
+%D Because we translated version 2 of this renderer into version 3 the following
+%D definitions may be sub optimal or more complex than actually needed.
+
+%D We will more more to lua ...
+
+% simple version
+
+\newcount\@MMLlevel \def\MMLcreset{\@MMLlevel\zerocount}
+
+\let\MMLctempresetlist\empty \def\setMMLcreset{\edef\MMLctempresetlist}
+
+\let\MMLdoL\donothing
+\let\MMLdoR\donothing
+
+\newcount\mmlapplydepth \def\MMLcreset{\mmlapplydepth\zerocount}
+
+\startxmlsetups mml:apply
+ \MMLmathinner {
+ % \xmldoif {#1} {/(\MMLcmainresetlist\string|\MMLctempresetlist)} {
+ % \MMLcreset
+ % }
+ \edef\mmlapplyopentoken {\xmlatt{#1}{open}}
+ \edef\mmlapplyclosetoken{\xmlatt{#1}{close}}
+ \ifcase\mmlapplydepth
+ \orelse\ifempty\mmlapplyopentoken
+ \def\mmlapplyopentoken {(}
+ \def\mmlapplyclosetoken{)}
+ \fi
+ \advance\mmlapplydepth\plusone
+ \begingroup
+ \ifempty\mmlapplyopentoken
+ \let\MMLdoL\donothing
+ \let\MMLdoR\donothing
+ \else
+ \edef\MMLdoL{\noexpand\left \mmlapplyopentoken }
+ \edef\MMLdoR{\noexpand\right\mmlapplyclosetoken}
+ \fi
+ \let\MMLctempresetlist\empty
+ \xmldoifelse {#1} {/mml:apply} {
+% % <apply> <apply> ... </apply> <ci> .. </ci> </apply>
+% \xmldoifelse {#1} {/mml:apply(mml:plus|mml:minus)} {% [a]
+% % yet incomplete and rather untested
+% % <apply> <apply> <minus/> <tan/> <cos/> </apply> <ci>x</ci> </apply>
+ } {% [b]
+% \MMLcreset
+ }
+% \MMLdoL
+% \mmlfirst{#1}
+% \ifconditional\somepostponedMMLactions
+% \postponedMMLactions
+% \else
+% \left(\MMLcreset\mmlsecond{#1}\right)
+% \fi
+% \MMLdoR
+% } {
+ \edef\mmlapplyaction{\xmlfilter{#1}{/*/tag()}}
+ \doifelsesetups {mml:apply:mml:\mmlapplyaction} {
+ \xmlsetup{#1}{mml:apply:mml:\mmlapplyaction}
+ } {
+% \MMLdoL
+ \xmlsetup{#1}{mml:\mmlapplyaction}
+% \MMLdoR
+ }
+% }
+ \endgroup
+ \advance\mmlapplydepth\minusone
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:apply:mml:apply
+ \xmlflush{#1}
+ \xmlall{#1}{../[position()>1]}
+\stopxmlsetups
+
+\startxmlsetups mml:apply:mml:fn
+ \xmldoifelse {#1} {/mml:fn/mml:ci} {
+ \edef\mmlfnci{\xmlstripped{#1}{/mml:fn/mml:ci}}
+ \doifelsesetups{mmc:fn:\mmlfnci} {
+ \xmlsetup{#1}{mmc:fn:\mmlfnci}
+ } {
+ \MMLcreset
+ \MMLdoL
+ \mmlfirst{#1}
+ \ifnum\xmlcount{#1}{/*}>\plusone
+ \negthinspace % not enough
+ \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
+ \fi
+ \MMLdoR
+ }
+ } {
+ \MMLcreset
+ \MMLdoL
+ \xmlall{#1}{/*}
+ \MMLdoR
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:apply:mml:csymbol
+ \xmlsetup{#1}{mml:csymbol}% \MMLdoL/MMLdoR to be handled in plugin
+\stopxmlsetups
+
+\startxmlsetups mml:apply:mml:ci
+ \xmlfirst{#1}{/mml:ci}
+ \ifnum\xmlcount{#1}{/*}>\plusone
+ \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
+ \fi
+\stopxmlsetups
+
+% reln
+
+\startxmlsetups mml:reln
+ \writestatus{XML}{MathML element "reln" is obsolete}
+\stopxmlsetups
+
+% fn
+
+% plusminus ±
+
+\startxmlsetups mmc:fn:\utfchar{"00B1}
+ \MMLdoL
+ \xmlconcat{#1}{/[position()>1]}{\utfchar{"00B1}}
+ \MMLdoR
+\stopxmlsetups
+
+% minusplus
+
+\startxmlsetups mmc:fn:\utfchar{"2213}
+ \MMLdoL
+ \xmlconcat{#1}{/[position()>1]}{\utfchar{"2213}}
+ \MMLdoR
+\stopxmlsetups
+
+\startxmlsetups mmc:fn
+ \begingroup
+ \edef\mmlnoffn{\xmlcount{#1}{/*}}
+ \ifnum\mmlnoffn>\plustwo
+ \def\MMCfnleft {\left(}
+ \def\MMCfnright{\right)}
+ \else
+ \let\MMCfnleft \relax
+ \let\MMCfnright\relax
+ \fi
+ \xmldoifelse {#1} {/mml:ci} {
+ \edef\mmlfnci{\xmltext{#1}{/mml:ci}}
+ \doifelsesetups{mmc:fn:\mmlfnci} {
+ \xmlsetup{#1}{mmc:fn:\mmlfnci}
+ } {
+ \MMLcreset
+ \mmlfirst{#1}
+ }
+ } {
+ \xmldoifelse {#1} {/mml:apply} {
+ \xmldoifelse {#1} {/(mml:plus\string|mml:minus)} {
+ \left(\mmlfirst{#1}\right)
+ } {
+ \mmlfirst{#1}
+ }
+ \ifnum\mmlnoffn>\plusone
+ \left(\xmlall{#1}{/!mml:apply}\right)
+ \fi
+ } {
+ \MMLcreset
+ \negthinspace
+ \MMCfnleft
+ \ifnum\mmlnoffn=\plustwo,\fi
+ \xmlconcat{#1}{/*}{2}{}{\MMLseparator,}
+ \MMCfnright
+ }
+ }
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mmc:fn:apply % where used?
+ \xmldoifelse {#1} {/mml:ci} {
+ \edef\mmlfnci{\xmltext{#1}{/mml:ci}}
+ \doifelsesetups{mmc:fn:\mmlfnci} {
+ \xmlsetup{#1}{mmc:fn:\mmlfnci}
+ } {
+ \MMLcreset
+ \mmlfirst{#1}
+ \ifnum\xmlcount{#1}{/*}>\plusone
+ \negthinspace
+ \left(\MMLcreset\xmlconcat{#1}{2}{}{\MMLseparator,}\right)
+ \fi
+ }
+ } {
+ \endgroup
+ \MMLcreset
+ \mmlfirst{#1}
+ }
+\stopxmlsetups
+
+%D The next definition provide a kind of plug-in mechanism (see the open math
+%D extension module).
+
+% http://www.publishers.com/somename
+%
+% called at the lua end
+
+\starttexdefinition mmlapplycsymbol #1#2#3#4
+ % #1=full url, #2=name, #3=encoding, #4=text
+ \doifelse {#3} {text} {
+ \text{#4}
+ } {
+ \doifelsesetups {mml:csymbol:#1} {
+ % full url
+ \fastsetup{mml:csymbol:#1}
+ } {
+ % somename (fallback)
+ \doifelsesetups {mml:csymbol:#2} {
+ \fastsetup{mml:csymbol:#2}
+ } {
+ \xmlval{mmc:cs}{#3}{}% todo
+ }
+ }
+ }
+\stoptexdefinition
+
+\startxmlsetups mml:csymbol
+ \mathml_csymbol{#1}
+\stopxmlsetups
+
+\startxmlsetups mml:csymbol:cdots
+ \cdots
+\stopxmlsetups
+
+% \startxmlsetups mml:csymbol:<url> \stopxmlsetups
+
+%D Alternative b will convert periods into comma's:
+
+\setupMMLappearance[cn] [\c!alternative=\v!a]
+\setupMMLappearance[polar] [\c!alternative=\v!a] % a|b|c
+\setupMMLappearance[float] [\c!symbol=\v!no] % \v!yes|dot
+\setupMMLappearance[enotation][\c!symbol=\v!no] % \v!yes|dot
+\setupMMLappearance[base] [\c!symbol=\v!numbers] % digits|characters|text|no
+
+\startxmlsetups mml:cs \xmlcommand{#1}{/}{mml:cs:\xmlattdef{#1}{type}{default}} \stopxmlsetups
+\startxmlsetups mml:ci \xmlcommand{#1}{/}{mml:ci:\xmlattdef{#1}{type}{default}} \stopxmlsetups
+\startxmlsetups mml:cn \xmlcommand{#1}{/}{mml:cn:\xmlattdef{#1}{type}{default}} \stopxmlsetups
+
+% helpers cn / todo: \mn{...}
+
+\startxmlsetups mml:cn:default
+ \mathopnolimits{\xmlflush{#1}}
+\stopxmlsetups
+
+% helpers ci
+
+\startxmlsetups mml:ci:default
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups mml:ci:set
+ {\blackboard{\xmlflush{#1}}} % todo
+\stopxmlsetups
+
+\startxmlsetups mml:ci:vector
+ \overrightarrow{\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups mml:ci:matrix
+ {\bi\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups mml:ci:function
+ \xmlflush{#1}% \negthinspace
+\stopxmlsetups
+
+\startxmlsetups mml:ci:fn
+ \xmlsetup{#1}{mml:ci:function}
+\stopxmlsetups
+
+\startxmlsetups mml:ci:complex-cartesian
+ \xmlsetup{#1}{mml:cn:complex}
+\stopxmlsetups
+
+\startxmlsetups mml:ci:complex
+ \xmlsetup{#1}{mml:cn:complex}
+\stopxmlsetups
+
+\startxmlsetups mml:ci:complex-polar
+ \xmlsetup{#1}{mml:cn:polar}
+\stopxmlsetups
+
+\startxmlsetups mml:ci:polar
+ \xmlsetup{#1}{mml:cn:polar}
+\stopxmlsetups
+
+% helpers ci
+
+\startxmlsetups mml:cn:default
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:integer
+ \edef\mmlintegerbase{\xmlattdef{#1}{base}{}}
+ \ifx\mmlintegerbase\empty
+ \xmlflush{#1}
+ \else
+ \doifelse \MMLbasesymbol \v!no {
+ \MMLcCNbasedata{\xmlflush{#1}}
+ } {
+ \MMLcCNbasedata{\xmlflush{#1}}\normalsubscript{
+ \hbox {\startimath
+ \mr
+ \scriptscriptstyle
+ \processaction
+ [\MMLbasesymbol]
+ [\v!characters=>\MMLcCNbasestring BODH,
+ \v!text=>\MMLcCNbasestring{BIN}{OCT}{DEC}{HEX},
+ \s!unknown=>\mmlintegerbase]
+ \stopimath}
+ }
+ }
+ \fi
+\stopxmlsetups
+
+\def\MMLcCNbasedata#1%
+ {\ifnum\mmlintegerbase>10 \relax{\mr#1}\else#1\fi}
+
+\def\MMLcCNbasestring#1#2#3#4%
+ {\ifnum\mmlintegerbase= 2 #1\orelse
+ \ifnum\mmlintegerbase= 8 #2\orelse
+ \ifnum\mmlintegerbase=10 #3\orelse
+ \ifnum\mmlintegerbase=16 #4\else
+ \mmlintegerbase \fi}
+
+\startxmlsetups mml:cn:polar
+ \xmlsetup{#1}{mml:cn:polar:\MMLpolaralternative}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:polar:a
+ \mathml_cpolar_a{#1}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:polar:b
+ {\mr e}\normalsuperscript{\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:polar:c
+ \exp\left(\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}\right)
+\stopxmlsetups
+
+\startxmlsetups mml:cn:complex-polar
+ \xmlsetup{#1}{mml:cn:polar}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:complex % todo ( )
+ \left(\xmlsnippet{#1}{1} + \xmlsnippet{#1}{3}\thinspace{\mr i}\right)
+\stopxmlsetups
+
+\startxmlsetups mml:cn:complex-cartesian
+ \xmlsetup{#1}{mml:cn:complex}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:float
+ \doifelse \MMLfloatsymbol \v!no {
+ % make sure that e shows up ok
+ \mathopnolimits{\xmlflush{#1}}
+ } {
+ % we should ignore \entities !
+ \edef\mmlfloatstring{\xmlflush{#1}}
+ \splitstring\mmlfloatstring\at e\to\first\and\last
+ \ifempty\first
+ \mmlfloatstring
+ \orelse\ifempty\last
+ \mmlfloatstring
+ \else
+ \first
+ \doifelse \MMLfloatsymbol {dot} \cdot \times
+ 10\normalsuperscript{\last}
+ \fi
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:cn:real
+ \xmlsetup{#1}{mml:cn:float}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:e-notation
+ \doifelse \MMLenotationsymbol \v!no {
+ \xmlsnippet{#1}{1}
+ \unskip\mathopnolimits{e}\ignorespaces
+ \xmlsnippet{#1}{3}
+ } {
+ \xmlsnippet{#1}{1}
+ \doifelse \MMLenotationsymbol {dot} \cdot
+ \times10\normalsuperscript{\xmlsnippet{#1}{3}}
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:cn:logical
+ \mathopnolimits{\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups mml:cn:rational
+ \xmldoifelse {#1} {/mml:sep} {
+ \mmlfrac
+ {\xmlsnippet{#1}{1}}
+ {\xmlsnippet{#1}{3}}
+ } {
+ \xmlflush{#1}
+ }
+\stopxmlsetups
+
+% interval
+
+\setupMMLappearance[interval][\c!alternative=\v!a,\c!separator={,}]
+
+% when empty element, then it's an apply
+
+\startxmlsetups mml:interval
+ \doifelse {\xmltag{#1}} {apply} {
+ % #1 == apply
+ \let\mmlintervalfirst \mmlsecond
+ \let\mmlintervalsecond\mmlthird
+ \xmlsetup{#1}{mml:interval:\xmlattributedef{#1}{/mml:interval}{closure}{closed}}
+ } {
+ % #1 == interval
+ \let\mmlintervalfirst \mmlfirst
+ \let\mmlintervalsecond\mmlsecond
+ \xmlsetup{#1}{mml:interval:\xmlattdef{#1}{closure}{closed}}
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:interval:closed
+ \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
+\stopxmlsetups
+
+\startxmlsetups mml:interval:open-closed
+ \doifelse \MMLintervalalternative \v!b {
+ \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
+ } {
+ \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:interval:closed-open
+ \doifelse \MMLintervalalternative \v!b {
+ \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right>
+ } {
+ \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right)
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:interval:open
+ \doifelse \MMLintervalalternative \v!b {
+ \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right>
+ } {
+ \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right)
+ }
+\stopxmlsetups
+
+% inverse
+
+\setfalse\xmlinversefunction
+
+\startxmlsetups mml:apply:inverse
+ \settrue\xmlinversefunction
+ \xmlsetup{#1}{mml:\xmlfilter{#1}{/mml:apply/*[2]/tag()}}
+\stopxmlsetups
+
+% condition
+
+% maybe a fast \xmlnonfirst
+
+% instead of the following we could do \xmlcontent{#1}{/mml:bvar} etc
+
+\startxmlsetups mml:bvar \xmlflush{#1} \stopxmlsetups
+\startxmlsetups mml:lowlimit \xmlflush{#1} \stopxmlsetups
+\startxmlsetups mml:uplimit \xmlflush{#1} \stopxmlsetups
+\startxmlsetups mml:degree \xmlflush{#1} \stopxmlsetups
+\startxmlsetups mml:logbase \xmlflush{#1} \stopxmlsetups
+\startxmlsetups mml:fn \xmlflush{#1} \stopxmlsetups
+
+\startxmlsetups mml:condition
+% \xmldoif {#1} {/mml:bvar} {
+% \xmlfirst{#1}{/mml:bvar}\mid
+% }
+ \xmlall{#1}{/!(mml:condition\string|mml:bvar)}
+\stopxmlsetups
+
+% declare
+
+\setupMMLappearance[declare][\c!state=\v!start]
+
+\startxmlsetups mml:declare
+ \doif \MMLdeclarestate \v!start {
+ \mathopnolimits{declare}
+ \mmlfirst{#1}
+ \ifnum\xmlcount{#1}{/*}>\plusone
+ \thickspace
+ \mathopnolimits{as}
+ \thickspace
+ \fi
+ \mmlsecond{#1}
+ }
+\stopxmlsetups
+
+% lambda
+
+\setupMMLappearance[lambda][\c!alternative=b]
+
+\startxmlsetups mml:lambda
+ \begingroup
+ \doifelse \MMLlambdaalternative \v!a {
+ \lambda\left(\xmlconcat{#1}{/!mml:lambda}{\MMLseparator,}\right)
+ } {
+ \ifnum\xmlcount{#1}{/mml:bvar}>\plusone
+ \left(\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}\right)
+ \else
+ \xmlfirst{#1}{/mml:bvar}
+ \fi
+ \mapsto
+ \MMLcreset
+ \xmlall{#1}{/!(mml:bvar|mml:lambda)}
+ }
+ \endgroup
+\stopxmlsetups
+
+% compose
+
+\startxmlsetups mml:compose
+ \begingroup
+ \MMLcreset
+% \let\MMLcCIfunction\firstofoneargument % brrr ? ? ?
+ \doifelsemmlfunction {#1} {
+ \left(\xmlconcat{#1}{/!mml:compose}{\circ}\right)
+ } {
+ \xmlconcat{#1}{/!mml:compose}{\circ}
+ }
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:image
+ \mathopnolimits{image} \left( {\mr\xmlfilter{#1}{/!mml:image/tag()}} \right)
+\stopxmlsetups
+
+\setupMMLappearance[piece][\c!separator=]
+
+\startxmlsetups mml:piecewise
+ \processaction
+ [\MMLpieceseparator]
+ [ \v!yes=>\def\theMMLpieceseparator{,&},
+ \v!no=>\def\theMMLpieceseparator{&},
+ \s!default=>\def\theMMLpieceseparator{&},
+ \s!unknown=>\def\theMMLpieceseparator{\,\,\hbox{\MMLpieceseparator}\,\,}]
+ \cases{\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups mml:piece
+ \mmlfirst{#1}\theMMLpieceseparator\mathematics{\mmlsecond{#1}}\crcr
+\stopxmlsetups
+
+\startxmlsetups mml:otherwise
+% \xmlflush{#1}\MMLcPIECEseparator&{\mr otherwise}\crcr
+ \xmlflush{#1}&{\mr otherwise}\crcr
+\stopxmlsetups
+
+% end of piece
+
+\startxmlsetups mml:quotient
+ \lfloor\mmlsecond{#1}/\mmlthird{#1}\rfloor
+\stopxmlsetups
+
+\startxmlsetups mml:factorial
+ \xmlall{#1}{/!factorial}!
+\stopxmlsetups
+
+\setupMMLappearance [divide] [\c!level=\!!maxcard,\c!alternative=\v!a]
+
+\newcount\mmldividelevel
+
+\startxmlsetups mml:divide
+ \advance\mmldividelevel\plusone
+ \doifelse \MMLdividealternative \v!b {
+ \mmlsecond{#1}/\mmlthird{#1}
+ } {
+ \ifnum \mmldividelevel > \MMLdividelevel \relax % threshold
+ \mmlsecond{#1}/\mmlthird{#1}
+ \else
+ \MMLcreset
+ \mmlfrac{\MMLcreset\mmlsecond{#1}}{\MMLcreset\mmlthird{#1}}
+ \fi
+ }
+ \advance\mmldividelevel\minusone
+\stopxmlsetups
+
+% min max
+
+\startxmlsetups mml:min \mathopnolimits{min} \xmlsetup{#1}{mml:minmax} \stopxmlsetups
+\startxmlsetups mml:max \mathopnolimits{max} \xmlsetup{#1}{mml:minmax} \stopxmlsetups
+
+\startxmlsetups mml:minmax
+ \xmldoif {#1} {/mml:bvar} {
+ {}\normalsubscript{\xmlfirst{#1}{/mml:bvar}}
+ }
+ \left\{
+ \xmlconcat{#1}{/!(mml:bvar\string|mml:max\string|mml:min)}{\MMLseparator,}
+ \right\}
+\stopxmlsetups
+
+% minus plus
+
+\setupMMLappearance [plus] [\c!alternative=\v!a] % b = no sign -> 3 1/4
+\setupMMLappearance [sign] [\c!reduction=\v!yes]
+
+% alternative b -> geen sign
+
+% branch needed, else (a-b) + (c-d) goes wrong
+% reset check in case of (-x) + 37
+% reset check in case of (-x) + 37
+
+\newcount\mmlpluscounter
+
+\startxmlsetups mml:plus
+ \doifelse \MMLsignreduction \v!yes {
+ \MMLdoL
+ \xmlsetup{#1}{mml:plus:reset}
+ \xmlcommand{#1}{/!mml:plus}{mml:plus:body}
+ \MMLdoR
+ } {
+ \ifnum\xmlcount{#1}{/!mml:plus}=\plusone
+ +\xmlfirst{#1}{/!mml:plus}
+ \else
+ \MMLdoL
+ \xmlconcat{#1}{/!mml:plus}{+}
+ \MMLdoR
+ \fi
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:plus:reset
+ \mmlpluscounter\zerocount
+\stopxmlsetups
+
+\startxmlsetups mml:plus:body
+ \advance\mmlpluscounter\plusone
+ \ifnum\mmlpluscounter>\plusone
+ \xmldoifelse{#1}{/mml:minus} {
+ \ifnum\xmlcount{#1}{/!mml:minus}>\plusone
+ +
+ \fi
+ } {
+ \doifelse {\xmlatt{#1}{type}} {rational} {
+ % fraction
+ } {
+ +
+ }
+ }
+ \fi
+ \xmldirect{#1}
+\stopxmlsetups
+
+\newcount\mmlminuscounter
+
+\startsetups mml:minus
+ \doifelse \MMLsignreduction \v!yes {
+ \ifnum\xmlcount{#1}{/!mml:minus}=\plusone
+ -\xmlfirst{#1}{/!mml:minus}
+ \else
+ \MMLdoL
+ \xmlsetup{#1}{mml:minus:reset}
+ \xmlcommand{#1}{/!mml:minus}{mml:minus:body}
+ \MMLdoR
+ \fi
+ } {
+ \left( % \MMLdoL
+ \ifnum\xmlcount{#1}{/!mml:minus}=\plusone
+ -\xmlfirst{#1}{/!mml:minus}
+ \else
+ \xmlsetup{#1}{mml:minus:reset}
+ \xmlcommand{#1}{/!mml:minus}{mml:minus:body}
+ \fi
+ \right) % \MMLdoR
+ }
+\stopsetups
+
+\startxmlsetups mml:minus:reset
+ \mmlminuscounter\zerocount
+\stopxmlsetups
+
+\startxmlsetups mml:minus:body
+ % we can also use concat here
+ \advance\mmlminuscounter\plusone
+ \ifnum\mmlminuscounter>\plusone
+ -
+ \fi
+ \xmldirect{#1}
+\stopxmlsetups
+
+% power
+
+\setupMMLappearance[power][\c!reduction=\v!yes]
+
+\let\MMLpowerelement\empty
+
+\startxmlsetups mml:power
+ \xmldoifelse {#1} {/mml:apply} {
+ \doifelse \MMLpowerreduction \v!yes {
+ \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist)} {
+ \gdef\MMLpowerelement{\mmlthird{#1}}% postpone, no xdef
+ \MMLcreset\mmlsecond{#1}
+ } {
+ \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}}
+ }
+ } {
+ \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}}
+ }
+ } {
+ \mmlsecond{#1}\normalsuperscript{\MMLcreset\mmlthird{#1}}
+ }
+\stopxmlsetups
+
+% rem
+
+\startxmlsetups mml:rem
+ \xmlconcat{#1}{/!mml:rem}{\mathopnolimits{mod}}
+\stopxmlsetups
+
+\setupMMLappearance [times] [\c!symbol=\v!no,\c!auto=\v!yes] % new, auto catches cn cn cn
+
+\startxmlsetups mml:times
+ \setMMLcreset{\MMLcfunctionlist\string|\MMLcconstructlist}%
+ \doifelse\MMLtimesauto\v!no {
+ \let\MMLtimes@@symbol\MMLtimessymbol
+ } {
+ \xmldoifelse {#1} {/mml:cn[name(1) == 'mml:cn']} {% name(1) is next one
+ \doifelseinset\MMLtimessymbol{\v!yes,\v!no} {
+ \let\MMLtimes@@symbol\v!yes
+ } {
+ \let\MMLtimes@@symbol\MMLtimessymbol
+ }
+ } {
+ \let\MMLtimes@@symbol\MMLtimessymbol
+ }
+ }
+ \doifelse\MMLtimes@@symbol\v!yes {
+ \xmlconcat{#1}{/!mml:times}{\times}
+ } {
+ \doifelse\MMLtimes@@symbol{dot} {
+ \xmlconcat{#1}{/!mml:times}{\cdot}
+ } {
+ \doifelse\MMLtimes@@symbol{times} {
+ \xmlconcat{#1}{/!mml:times}{\times}
+ } {
+ \xmlall{#1}{/!mml:times}
+ }
+ }
+ }
+\stopxmlsetups
+
+\setupMMLappearance[root][\c!symbol=\v!yes]
+
+\startxmlsetups mml:root
+ \xmldoifelse {#1} {/mml:degree} {
+ \root
+ \doifnot\MMLrootsymbol\v!no{\MMLcreset\xmltext{#1}{/mml:degree}}
+ \of
+ } {
+ \sqrt
+ }
+ {\MMLcreset\xmlall{#1}{/!(mml:degree\string|mml:root)}}
+\stopxmlsetups
+
+% gcd
+
+\startxmlsetups mml:gcd
+ \begingroup
+ \gcd\left(\MMLcreset\xmlconcat{#1}{/!mml:gcd}{\MMLseparator,}\right)
+ \endgroup
+\stopxmlsetups
+
+% and or xor implies, not
+
+\startxmlsetups mml:and \xmlconcat{#1}{/!mml:and} {\wedge} \stopxmlsetups
+\startxmlsetups mml:or \xmlconcat{#1}{/!mml:or} {\vee} \stopxmlsetups
+\startxmlsetups mml:xor \xmlconcat{#1}{/!mml:xor} {\mathopnolimits{xor}} \stopxmlsetups
+\startxmlsetups mml:implies \xmlconcat{#1}{/!mml:implies}{\Rightarrow} \stopxmlsetups
+\startxmlsetups mml:not \neg \xmlall {#1}{/!mml:not} \stopxmlsetups
+
+% forall exists
+
+%D We need to shift left below rotated A.
+
+\startxmlsetups mml:forall
+ \forall \negthinspace \xmlsetup{#1}{mml:forallexists}
+\stopxmlsetups
+
+\startxmlsetups mml:exists
+ \exists \xmlsetup{#1}{mml:forallexists}
+\stopxmlsetups
+
+\def\mmlforallexistslist{mml:bvar\string|mml:forall\string|mml:exists\string|mml:condition}
+
+\startxmlsetups mml:forallexists
+ \normalsubscript{\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}}
+ \xmldoifelse {#1} {/mml:condition} {
+ \thickspace
+ \begingroup
+ \xmlfirst{#1}{/mml:condition}
+ \endgroup
+ \ifcase\xmlcount{#1}{/!(\mmlforallexistslist)}\relax
+ % nothing
+ \or
+ % == snelle volgende
+ \left\vert
+ \MMLcreset \medspace \xmlconcat{#1}{/!(\mmlforallexistslist)}{}
+ \right.
+ \else
+ % special case
+ \left\vert
+ \matrix {
+ \xmlconcat{#1}{/!(\mmlforallexistslist)}{\hfill\crcr}
+ }
+ \right.
+ \fi
+ } {
+ :\xmlfirst{#1}{/!(\mmlforallexistslist)}
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:abs
+ \left\vert \MMLcreset\xmlall{#1}{/!mml:abs} \right\vert
+\stopxmlsetups
+
+\startxmlsetups mml:conjugate % watch extra {}
+ {\overline{\MMLcreset\xmlall{#1}{/!mml:conjugate}}}
+\stopxmlsetups
+
+\startxmlsetups mml:arg
+ \mathopnolimits{arg} \left( \MMLcreset\xmlall{#1}{/!mml:arg} \right)
+\stopxmlsetups
+
+\startxmlsetups mml:real
+ \Re \left( \MMLcreset \xmlall{#1}{/!mml:real} \right)
+\stopxmlsetups
+
+\startxmlsetups mml:imaginary
+ \Im \ left( \MMLcreset \xmlall{#1}{/!mml:imaginary} \right)
+\stopxmlsetups
+
+\startxmlsetups mml:lcm
+ \mathopnolimits{lcm} \left( \xmlconcat{#1}{/!mml:lcm}{\MMLseparator,} \right)
+\stopxmlsetups
+
+\startxmlsetups mml:floor
+ \lfloor \xmlall{#1}{/!mml:floor} \rfloor
+\stopxmlsetups
+
+\startxmlsetups mml:ceiling
+ \lceiling \xmlall{#1}{/!mml:ceiling} \rceiling
+\stopxmlsetups
+
+% relations
+
+% apply attr or eq
+
+\setupMMLappearance[relation][\c!align=\v!no]
+
+\xmlmapvalue {mml:relation} {eq} {=}
+\xmlmapvalue {mml:relation} {neq} {\neq}
+\xmlmapvalue {mml:relation} {gt} {>}
+\xmlmapvalue {mml:relation} {lt} {<}
+\xmlmapvalue {mml:relation} {geq} {\geq}
+\xmlmapvalue {mml:relation} {leq} {\leq}
+\xmlmapvalue {mml:relation} {equivalent} {\equiv}
+\xmlmapvalue {mml:relation} {approx} {\approx}
+\xmlmapvalue {mml:relation} {factorof} {\mid}
+
+\startxmlsetups mml:eq \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:neq \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:gt \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:lt \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:geq \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:leq \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:equivalent \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:approx \xmlsetup{#1}{mml:relation} \stopxmlsetups
+\startxmlsetups mml:factorof \xmlsetup{#1}{mml:relation} \stopxmlsetups
+
+\startxmlsetups mml:relation
+ \edef\mmlapplyaction{\xmlfilter{#1}{/*/tag()}}
+ \MMLcreset \xmlsetup{#1}{mml:relation:\xmlattdef{#1}{align}{\MMLrelationalign}}
+\stopxmlsetups
+
+\startxmlsetups mml:relation:default
+ \xmlconcatrange{#1}{/*}{2}{}{\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}}
+\stopxmlsetups
+\startxmlsetups mml:relation:last
+ \eqalign {
+ \xmlconcatrange{#1}{/*}{2}{-2}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr}
+ \mmlprelast{#1}&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}\mmllast{#1}
+ }
+\stopxmlsetups
+\startxmlsetups mml:relation:first
+ \eqalign {
+ \mmlsecond{#1}\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}
+ &\xmlconcatrange{#1}{/*}{3}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
+ }
+\stopxmlsetups
+\startxmlsetups mml:relation:left
+ \eqalign {
+ \xmlconcatrange{#1}{/*}{2}{}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr}
+ }
+\stopxmlsetups
+\startxmlsetups mml:relation:right
+ \eqalign {
+ &\xmlconcatrange{#1}{/*}{2}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
+ }
+\stopxmlsetups
+\startxmlsetups mml:relation:no
+ \xmlsetup{#1}{mml:relation:default}
+\stopxmlsetups
+\startxmlsetups mml:relation:yes
+ \xmlsetup{#1}{mml:relation:left}
+\stopxmlsetups
+
+% personal goody:
+
+\edef\MMLcmainresetlist{\MMLcmainresetlist\string|becomes}
+
+\xmlmapvalue {mml:relation} {mml:becomes} {:=}
+
+\startxmlsetups mml:becomes \xmlsetup{#1}{mml:relation} \stopxmlsetups
+
+% calculus and vector calculus
+
+\startxmlsetups mml:domainofapplication
+ \xmlall{#1}{/!mml:domainofapplication}
+\stopxmlsetups
+
+\setupMMLappearance[int][\c!location=\v!top]
+
+\def\doMMLlimits#1{\doifelsevalue{MML#1\c!location}\v!top\limits\nolimits}
+
+\startxmlsetups mml:int
+ \MMLcreset
+ \xmldoifelse {#1} {/mml:domainofapplication} {
+ \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:domainofapplication}}\relax
+ } {
+ \xmldoifelse {#1} {/mml:condition} {
+ \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:condition}}\relax
+ } {
+ \xmldoifelse {#1} {/mml:lowlimit} {
+ \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:lowlimit}}\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}}
+ } {
+ % funny, why do we have lowlimit/uplimit then
+ \xmldoifelse {#1} {/mml:apply/mml:interval} {
+ \int \doMMLlimits{int}\normalsubscript{\xmlindex{#1}{/mml:apply}{2}}\normalsuperscript{\xmlindex{#1}{/mml:apply}{3}}
+ } {
+ \int
+ }
+ }
+ }
+ }
+ \MMLcreset
+ \xmldoifelse {#1} {/mml:apply} {
+ \doifelsemmlfunction {#1} { % todo test
+ \xmlfirst{#1}{/mml:apply}
+ } {
+ % if there are too many () now, we need to be more clever
+ \left( \xmlfirst{#1}{/mml:apply} \right)
+ }
+ } {
+ \xmlfirst{#1}{/mml:ci}
+ }
+ \xmldoifelse {#1} {/mml:bvar} {
+ \thinspace {\mr d} \xmlfirst{#1}{/mml:bvar}
+ } {
+ % nothing
+ }
+\stopxmlsetups
+
+\setupMMLappearance[diff][\c!location=\v!top,\c!alternative=\v!a]
+
+\startxmlsetups mml:diff
+ \MMLcreset
+ \doifelse \MMLdiffalternative \v!a {
+ \xmldoifelse {#1} {/mml:lambda} {
+ % a special case (mathadore/openmath)
+ \mmlfrac {
+ d
+ \normalsuperscript
+ {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
+ {\xmlfirst{#1}{/mml:lambda}\xmlfirst{#1}{/mml:ci}}
+ } {
+ d
+ {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:ci}}
+ \normalsuperscript
+ {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
+ }
+ } {
+ \xmldoifelse {#1} {/mml:bvar} {
+ \mmlfrac {
+ {\mr d}{
+ \xmldoifelse {#1} {/mml:degree} {
+ \normalsuperscript{\xmlconcat{#1}{/mml:degree}\empty}
+ } {
+ \xmldoif {#1} {/mml:bvar/mml:degree} {
+ \normalsuperscript{\xmlconcat{#1}{/mml:bvar/mml:degree}+}
+ }
+ }
+ }
+ \doif \MMLdifflocation \v!top {
+ \xmldoifelse {#1} {/mml:ci} {
+ \xmlfirst{#1}{/mml:ci}
+ } {
+ \MMLcreset
+ \ifnum\xmlcount{#1}{/mml:apply/*}>\plustwo % hack
+ \left(\xmlfirst{#1}{/mml:apply}\right)
+ \else
+ \xmlfirst{#1}{/mml:apply}
+ \fi
+ }
+ }
+ } {
+ {\mr d}
+ \xmlfirst{#1}{/mml:bvar/!mml:degree}
+ \xmldoif {#1} {/mml:bvar/mml:degree} {
+ \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}}
+ }
+ }
+ \doifnot \MMLdifflocation \v!top {
+ \left(\MMLcreset\xmlfirst{#1}{/(mml:apply\string|mml:ci)}\right)
+ }
+ } {
+ % beware, the second {} is needed for the superscript
+ \xmlconcatrange{#1}{/*}{2}{}{}\normalsuperscript\prime
+ }
+ }
+ } {
+ \MMLcreset
+ \xmlfirst{#1}{/(mml:apply\string|mml:ci)}
+ % there can be problems with nested diff's: \normalsuperscript\normalsuperscript{} error
+ % so we add an empty group here
+ {}\normalsuperscript
+ {
+ \xmldoifelse {#1} {/mml:degree} {
+ \edef\mmldegree{\xmlfirst{#1}{/mml:degree/mml:cn}}
+ \ifempty\mmldegree
+ % what to do here
+ \else
+ \dorecurse\mmldegree\prime
+ \fi
+ } {
+ \prime
+ }
+ }
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:partialdiff
+ \xmldoifelse {#1} {/mml:list} {
+ {\mr D}\normalsubscript{
+ \begingroup
+ \setfalse\mmllistdelimiters
+ \xmlall{#1}{/mml:list}
+ \endgroup
+ }
+ \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
+ } {
+ \xmldoifelse {#1} {/mml:bvar} {
+ \mmlfrac {
+ {\mr d}\normalsuperscript{
+ \xmldoifelse {#1} {/mml:degree} {
+ \xmlconcat{#1}{/mml:degree}\empty
+ } {
+ \xmlconcat{#1}{/mml:bvar/mml:degree}+
+ }
+ }
+ \MMLcreset
+ \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
+ } {
+ \xmldoif {#1}{/mml:bvar/!mml:degree} {
+ \xmlfirst{#1}{/mml:bvar/!mml:degree} \,
+ }
+ {\mr d}\xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
+ \xmldoif {#1} {/mml:bvar/mml:degree} {
+ \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}}
+ }
+ }
+ } {
+ \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
+ }
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:divergence \mathopnolimits{div} \xmlall{#1}{/!mml:divergence} \stopxmlsetups
+\startxmlsetups mml:grad \mathopnolimits{grad} \xmlall{#1}{/!mml:grad} \stopxmlsetups
+\startxmlsetups mml:curl \mathopnolimits{curl} \xmlall{#1}{/!mml:curl} \stopxmlsetups
+\startxmlsetups mml:laplacian \nabla\normalsuperscript2 \xmlall{#1}{/!mml:laplacian} \stopxmlsetups
+\startxmlsetups mml:ident \mathopnolimits{identity} \xmlall{#1}{/!mml:ident} \stopxmlsetups
+
+\setupMMLappearance[domain] [symbol=]
+\setupMMLappearance[codomain][symbol=]
+
+\startxmlsetups mml:domain
+ \doifelsenothing \MMLdomainsymbol {
+ \mathopnolimits{domain}\MMLcreset\xmlall{#1}{/!mml:domain}
+ } {
+ \MMLdomainsymbol\normalsubscript{\xmlall{#1}{/!mml:domain}}
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:codomain
+ \doifelsenothing \MMLcodomainsymbol {
+ \mathopnolimits{codomain}\MMLcreset\xmlall{#1}{/!mml:codomain}
+ } {
+ \MMLcodomainsymbol\normalsubscript{\xmlall{#1}{/!mml:codomain}}
+ }
+\stopxmlsetups
+
+% theory of sets
+
+\startxmlsetups mml:set
+ \left\{
+ \xmldoifelse {#1} {/mml:condition} {
+ \xmlfirst{#1}{/mml:bvar}\,\middle\vert\,\xmlfirst{#1}{/mml:condition}
+ } {
+ \xmlconcat{#1}{/!mml:set}{\MMLseparator,}
+ }
+ \right\}
+ \relax % needed
+\stopxmlsetups
+
+\settrue\mmllistdelimiters
+
+\startxmlsetups mml:list
+ \begingroup
+ \ifconditional\mmllistdelimiters\left [\fi
+ \begingroup
+ \settrue\mmllistdelimiters
+ \xmlconcat{#1}{/!mml:list}{\MMLseparator,}
+ \endgroup
+ \ifconditional\mmllistdelimiters\right]\fi
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:union \mmlsecond{#1} \cup \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:intersect \mmlsecond{#1} \cap \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:in \mmlsecond{#1} \in \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:notin \mmlsecond{#1} {\not\in} \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:subset \mmlsecond{#1} \subset \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:prsubset \mmlsecond{#1} \subseteq \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:notsubset \mmlsecond{#1} {\not\subset} \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:notprsubset \mmlsecond{#1} {\not\subseteq} \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:setdiff \mmlsecond{#1} \setminus \mmlthird{#1} \stopxmlsetups
+
+\startxmlsetups mml:card
+ \left\vert \xmlall{#1}{/!mml:card} \right\vert
+\stopxmlsetups
+
+\startxmlsetups mml:cartesianproduct
+ \xmlconcat{#1}{/!mml:cartesianproduct}{\times}
+\stopxmlsetups
+
+% sequences and series
+
+\setupMMLappearance[sum] [\c!location=\v!top]
+\setupMMLappearance[product][\c!location=\v!top]
+
+\xmlmapvalue {mml:sumprod} {sum} {\sum}
+\xmlmapvalue {mml:sumprod} {product} {\prod}
+
+\startxmlsetups mml:sum \edef\mmlsumprodname{sum} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups
+\startxmlsetups mml:product \edef\mmlsumprodname{product} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups
+
+\def\mmlstackedsubscripts#1%
+ {\vbox
+ {\baselineskip\zeropoint % hack, taco vragen
+ \halign{\startimath\scriptstyle\hss\alignmark\alignmark\hss\stopimath\cr#1\crcr}}}
+
+% unfinished
+
+\startxmlsetups mml:sumprod
+ \begingroup
+ \xmldoifelse {#1} {/(mml:condition\string|mml:bvar\string|mml:lowlimit)} {
+ \def\mmlsumprodlower{
+ \normalsubscript{
+ \xmldoifelse {#1} {/mml:condition} {
+ \mmlstackedsubscripts{\xmlconcat{#1}{/mml:condition}{\crcr}}
+ } {
+ \xmldoif {#1} {/mml:bvar} {
+ \xmlfirst{#1}{/mml:bvar}
+ \xmldoif{#1}{/mml:lowlimit}{=}
+ }
+ \xmlfirst{#1}{/mml:lowlimit}
+ }
+ }
+ }
+ } {
+ \let\mmlsumprodlower\empty
+ }
+ \xmldoifelse {#1} {/mml:uplimit} {
+ \def\mmlsumprodupper{\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}}}
+ } {
+ \let\mmlsumprodupper\empty
+ }
+ \xmldoif {#1} {/mml:interval} { % open math converter gives this
+ \edef\mmlintervalfrom{\xmlindex{#1}{/mml:interval}{1}}
+ \edef\mmlintervalto {\xmlindex{#1}{/mml:interval}{2}}
+ \ifempty\mmlintervalfrom \else
+ \def\mmlsumprodlower{\normalsubscript{\xmldoif{#1}{/mml:bvar}{\xmlfirst{#1}{/mml:bvar}{=}}\mmlintervalfrom}}
+ \fi
+ \ifempty\mmlintervalto \else
+ \def\mmlsumprodupper{\normalsuperscript{\mmlintervalto}}
+ \fi
+ }
+ \MMLcreset
+ \xmlval{mml:sumprod}{\mmlsumprodname}{}\doMMLlimits\mmlsumprodname\mmlsumprodupper\mmlsumprodlower
+ \MMLcreset
+ \xmldoifelse {#1} {/mml:lambda/mml:apply} {
+ \xmlfirst{#1}{/mml:lambda/mml:apply}% a bit of open math conversion mess
+ } {
+ \xmlfirst{#1}{/(mml:apply\string|mml:lambda\string|mml:ci)}%
+ }
+ \endgroup
+\stopxmlsetups
+
+\setupMMLappearance[limit][\c!location=\v!top]
+
+\startxmlsetups mml:limit
+ \MMLcreset \lim
+ \doMMLlimits {limit}\normalsubscript{
+ \MMLcreset
+ \xmldoifelse {#1} {/mml:condition} {
+ \xmlfirst{#1}{/mml:condition}
+ } {
+ \xmldoif {#1} {/mml:bvar} {
+ \xmlfirst{#1}{/mml:bvar}\rightarrow
+ }
+ \xmlfirst{#1}{/mml:lowlimit}
+ }
+ }
+ \begingroup
+ % a bit of open math conversion mess, lambda needed for openmath, ok?
+ \MMLcreset
+ \xmlfirst{#1}{/mml:lambda/mml:apply}
+ \xmlfirst{#1}{/(mml:apply\string|mml:lambda)}
+ \endgroup
+\stopxmlsetups
+
+% consider a faster index
+
+\startxmlsetups mml:tendsto
+ \MMLcreset \mmlsecond{#1}
+ \xmlval {mml:tendsto:type} {\xmlattdef{#1}{type}{default}} {\rightarrow}
+ \MMLcreset \mmlthird{#1}
+\stopxmlsetups
+
+\xmlmapvalue {mml:tendsto:type} {above} {\downarrow}
+\xmlmapvalue {mml:tendsto:type} {below} {\uparrow}
+\xmlmapvalue {mml:tendsto:type} {default} {\rightarrow}
+
+% elementary classical functions
+
+\setupMMLappearance[log][\c!location=\v!right]
+
+\startxmlsetups mml:exp
+% {\mr e}\normalsuperscript{\xmlfirst{#1}{/mml:apply\string|mml:reln\string|mml:ci\string|mml:cn}}
+ {\mr e}\normalsuperscript{\xmlfirst{#1}{/!mml:exp}}
+\stopxmlsetups
+
+\startxmlsetups mml:log
+ \xmldoifelse {#1} {/mml:logbase} {
+ \doifelse \MMLloglocation \v!left {
+ \mathop {
+ {}\normalsuperscript{\xmlfirst{#1}{/mml:logbase}}\negthinspace\mathopnolimits{log}
+ }
+ } {
+ \mathopnolimits{log}\normalsubscript{\xmlfirst{#1}{/mml:logbase}}
+ }
+% \MMLcreset
+ \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
+% \xmlsetup{#1}{mml:function} % todo, we start elsewhere
+% \mmlthird{#1}
+ } {
+ \mathopnolimits{log}
+% \MMLcreset
+% \xmlsetup{#1}{mml:function} % todo, we start elsewhere
+ \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
+% \mmlsecond{#1}
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:ln
+ \mathopnolimits{ln}
+ \xmlsetup{#1}{mml:function}
+\stopxmlsetups
+
+% statistics
+
+\startxmlsetups mml:mean \overline {\mmlsecond{#1}} \stopxmlsetups
+\startxmlsetups mml:sdev \sigma \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
+\startxmlsetups mml:variance \sigma \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript2 \stopxmlsetups
+\startxmlsetups mml:median \mathopnolimits{median}\left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
+\startxmlsetups mml:mode \mathopnolimits{mode} \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
+
+% moments
+
+\startxmlsetups mml:moment
+ \left\langle
+ \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}\normalsuperscript{\xmlfirst{#1}{/mml:degree}}
+ \right\rangle
+ \xmldoif {#1} {mml:momentabout} {
+ \normalsubscript{\xmlfirst{#1}{mml:momentabout}}
+ }
+\stopxmlsetups
+
+% linear algebra
+
+\setupMMLappearance [vector] [\c!direction=\v!horizontal,\c!separator={,}]
+
+\startxmlsetups mml:vector
+ \begingroup
+ \ifnum\xmlcount{#1}{/*}>\plusone
+ \doifelse\MMLvectordirection\v!horizontal {
+ \left(\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}\right)
+ } {
+ \MMLcreset\left(\matrix{\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}}\right)
+ }
+ \else
+ \overrightarrow{\charhtstrut\mmlfirst{#1}}
+ \fi
+ \endgroup
+\stopxmlsetups
+
+\settrue\MMCdelmatrix % ( ) when true
+
+\startxmlsetups mml:matrix
+ \begingroup
+ \MMLcreset
+ \ifconditional\MMCdelmatrix
+ \left(\matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}}\right)
+ \else
+ \settrue\MMCdelmatrix
+ \matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}}
+ \fi
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:matrixrow
+ \begingroup
+ \MMLcreset
+ \left(\xmlsetup{#1}{mml:matrixrow:do}\right)
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:matrixrow:do
+ \xmlconcat{#1}{/*}{&}\crcr
+\stopxmlsetups
+
+\startxmlsetups mml:determinant
+ \begingroup
+ \setfalse\MMCdelmatrix
+ \left|\mmlsecond{#1}\right|
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:transpose
+ \mmlsecond{#1}\normalsuperscript{\mathopnolimits{T}}
+\stopxmlsetups
+
+\startxmlsetups mml:selector
+ \MMLmathinner{\mmlsecond{#1}\normalsubscript{\MMLcreset\xmlconcatrange{#1}{/*}{3}{}{\MMLseparator,}}}
+\stopxmlsetups
+
+\startxmlsetups mml:vectorproduct \mmlsecond{#1}\times \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:scalarproduct \mmlsecond{#1}\cdot \mmlthird{#1} \stopxmlsetups
+\startxmlsetups mml:outerproduct \mmlsecond{#1}\otimes\mmlthird{#1} \stopxmlsetups
+
+% semantic mapping elements
+
+\setupMMLappearance[semantics][\c!state=\v!start]
+
+\startxmlsetups mml:semantics
+ \doifelse\MMLsemanticsstate\v!start {
+ \xmlall{#1}{/mml:annotation}
+ } {
+ \xmlall{#1}{/!mml:annotation}
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:annotation
+ \xmldoifelse {#1} {.[oneof(@encoding,'TeX','tex','application/x-tex','TEX','ConTeXt','context','CONTEXT','ctx')]} {
+ \xmlflushcontext{#1}
+ } {
+ \xmldoifelse {#1} {.[oneof(@encoding,'calcmath','cm')]} {
+ \expanded{\calcmath{\xmlflush{#1}}}
+ } {
+ \xmldoifelse {#1} {.[oneof(@encoding,'asciimath','am')]} {
+ \ifdefined\asciimath
+ \expanded{\asciimath{\xmlflushpure{#1}}}
+ \else
+ \hbox{\tt no am loaded}
+ \fi
+ } {
+ \xmlall{#1}{../!mml:annotation}
+ }
+ }
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:annotation-xml
+ % maybe diagnostics
+\stopxmlsetups
+
+% misc
+
+\startxmlsetups mml:integers \integers \stopxmlsetups
+\startxmlsetups mml:reals \reals \stopxmlsetups
+\startxmlsetups mml:rationals \rationals \stopxmlsetups
+\startxmlsetups mml:naturalnumbers \naturalnumbers \stopxmlsetups
+\startxmlsetups mml:complexes \complexes \stopxmlsetups
+\startxmlsetups mml:primes \primes \stopxmlsetups
+\startxmlsetups mml:exponentiale \mathopnolimits{e} \stopxmlsetups
+\startxmlsetups mml:imaginaryi \mathopnolimits{i} \stopxmlsetups
+\startxmlsetups mml:notanumber \mathopnolimits{NaN} \stopxmlsetups
+\startxmlsetups mml:true \mathopnolimits{true} \stopxmlsetups
+\startxmlsetups mml:false \mathopnolimits{false} \stopxmlsetups
+\startxmlsetups mml:emptyset \mathopnolimits{Ø} \stopxmlsetups
+\startxmlsetups mml:pi \pi \stopxmlsetups
+\startxmlsetups mml:eulergamma \gamma \stopxmlsetups
+\startxmlsetups mml:infinity \infty \stopxmlsetups
+
+% gonio functions
+
+\setupMMLappearance[function][\c!reduction=\v!yes]
+
+% todo: \mfunction which adapts itself when registered as command
+
+% todo: \def\mmlcfunction#1#2{\mathopnolimits{#2}\xmlsetup{#1}{mml:function}}
+
+\startxmlsetups mml:sin \mathcommand {sin}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:sinh \mathcommand {sinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:cos \mathcommand {cos}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:cosh \mathcommand {cosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:tan \mathcommand {tan}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:tanh \mathcommand {tanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:cot \mathcommand {cot}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:coth \mathcommand {coth}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:csc \mathcommand {csc}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:csch \mathcommand {csch}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:sec \mathcommand {sec}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:sech \mathcommand {sech}\xmlsetup{#1}{mml:function} \stopxmlsetups
+
+\startxmlsetups mml:arcsin \mathcommand {arcsin}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arcsinh \mathcommand{arcsinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccos \mathcommand {arccos}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccosh \mathcommand{arccosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arctan \mathcommand {arctan}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arctanh \mathcommand{arctanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccot \mathcommand {arccot}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccoth \mathcommand{arccoth}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccsc \mathcommand {arccsc}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccsch \mathcommand{arccsch}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arcsec \mathcommand {arcsec}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arcsech \mathcommand{arcsech}\xmlsetup{#1}{mml:function} \stopxmlsetups
+
+\startxmlsetups mml:function
+ \ifempty\MMLpowerelement
+ \ifconditional\xmlinversefunction\normalsuperscript{-1}\fi
+ \setfalse\xmlinversefunction
+ \else
+ \normalsuperscript{\ifconditional\xmlinversefunction-\fi\MMLpowerelement}
+ \setfalse\xmlinversefunction
+ \glet\MMLpowerelement\empty
+ \fi
+ \xmlsetup{#1}{mml:function:argument}
+\stopxmlsetups
+
+\startxmlsetups mml:function:argument
+ \doifelse \MMLfunctionreduction \v!yes {
+ \xmldoifelse {#1} {/mml:apply} {
+ \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist\string|mml:divide)}
+ \donefalse
+ \donetrue
+ } {
+ \donefalse
+ }
+ } {
+ \donetrue
+ }
+ % beware, we still flush from 2 up
+ \ifdone
+ \left(
+ \MMLcreset
+ \xmlall{#1}{/[position()>1]}% \xmlconcatrange{#1}{/*}{2}{}\empty
+ \right)
+ \else
+ \MMLcreset
+ \xmlall{#1}{/[position()>1]}
+ \fi
+\stopxmlsetups
+
+% PRESENTATION MATHML
+
+% helpers: maybe we can need a setting for the uprights
+
+\xmlmapvalue {mml:s} {normal} {\mathupright} % {\mathtf}
+\xmlmapvalue {mml:s} {double-struck} {\mathblackboard}
+\xmlmapvalue {mml:s} {italic} {\mathit}
+\xmlmapvalue {mml:s} {fraktur} {\mathfraktur}
+\xmlmapvalue {mml:s} {script} {\mathscript}
+\xmlmapvalue {mml:s} {bold} {\mb} % {\mathbf}
+\xmlmapvalue {mml:s} {bold-italic} {\mathbi}
+\xmlmapvalue {mml:s} {bold-fraktur} {\mathfraktur\mathbf}
+\xmlmapvalue {mml:s} {bold-script} {\mathscript\mathbf}
+\xmlmapvalue {mml:s} {sans-serif} {\mathss}
+\xmlmapvalue {mml:s} {bold-sans-serif} {\mathss\mathbf}
+\xmlmapvalue {mml:s} {sans-serif-italic} {\mathss\mathit}
+\xmlmapvalue {mml:s} {sans-serif-bold-italic} {\mathss\mathbi}
+\xmlmapvalue {mml:s} {monospace} {\mathtt}
+
+\xmlmapvalue {mml:l} {-} {\let\mmlfrac\tfrac}
+ \let\mmlfrac\frac
+\xmlmapvalue {mml:l} {+} {\let\mmlfrac\sfrac}
+
+\xmlmapvalue {mml:d} {true} {\displaystyle}
+\xmlmapvalue {mml:d} {false} {\textstyle} % or whatever
+
+\starttexdefinition setmmlmathstyle #1
+ \ifxmlattempty{#1}{displaystyle}\else
+ \xmlval{mml:d}\xmllastatt\empty
+ \fi
+ \ifxmlattempty{#1}{mathvariant}\else
+ \xmlval{mml:s}\xmllastatt\empty
+ \fi
+\stoptexdefinition
+
+\starttexdefinition setmmlscriptlevel #1
+ \ifxmlattempty{#1}{scriptlevel}
+ \let\mmlfrac\frac
+ \else
+ \xmlval{mml:l}\xmllastatt{\let\mmlfrac\frac}
+ \fi
+\stoptexdefinition
+
+\starttexdefinition setmmlmathcolor #1
+ \ifxmlattempty{#1}{mathcolor}\else
+ \directcolor[\xmllastatt]
+ \fi
+\stoptexdefinition
+
+\starttexdefinition setmmlmathproperties #1
+ % \ifxmlatt{#1}{displaystyle}\empty\else
+ \ifxmlattempty{#1}{displaystyle}\else
+ \xmlval{mml:d}\xmllastatt\empty
+ \fi
+ \ifxmlattempty{#1}{mathvariant}\else
+ \xmlval{mml:s}\xmllastatt\empty
+ \fi
+ \ifxmlattempty{#1}{scriptlevel}
+ \let\mmlfrac\frac
+ \else
+ \xmlval{mml:l}\xmllastatt{\let\mmlfrac\frac}
+ \fi
+ \ifxmlattempty{#1}{mathcolor}\else
+ \directcolor[\xmllastatt]
+ \fi
+\stoptexdefinition
+
+% todo: textbackgrounds / todo: can be combined with new grouping
+
+\starttexdefinition applymmlmathbackground #1#2
+ \ifxmlattempty{#1}{mathbackground}
+ #2
+ \else
+ \backgroundline[\xmllastatt]{#2}
+ \fi
+\stoptexdefinition
+
+\starttexdefinition applymmlsometext #1#2
+ \begingroup
+ \applymmlmathbackground {#1} {
+ \setmmlmathcolor {#1}
+ \setmmlmathstyle {#1}
+ #2
+ }
+ \endgroup
+\stoptexdefinition
+
+% setups
+
+\startxmlsetups mml:mi % todo: mathsize (unlikely) mathcolor (easy) mathbackground (easy)
+ \begingroup
+ \pushmathstyle % still needed ?
+ \setmmlmathproperties{#1}
+ \mathml_mi{#1}
+ \popmathstyle % still needed ?
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:mn
+ \begingroup
+ \setmmlmathcolor{#1}
+ \mathml_mn{#1}
+ \endgroup
+\stopxmlsetups
+
+% <m:mo>-</m:mo><m:mn>2</m:mn> and <m:mn>1</m:mn><m:mo>-</m:mo><m:mn>2</m:mn>
+%
+% spacing between - and 2 is taken care of by tex itself
+
+\startxmlsetups mml:mo
+ \begingroup
+ \setmmlmathcolor{#1}
+ \ifxmlatt{#1}{maxsize}{1}
+ \settrue\mmlignoredelimiter
+ \orelse\ifxmlatt{#1}{stretchy}{false}
+ \settrue\mmlignoredelimiter
+ \fi
+ \ifxmlattempty{#1}{lspace}\else
+ \hskip\xmllastatt\relax % todo: check for dimension
+ \fi
+ \mathml_mo{#1}
+ \ifxmlattempty{#1}{rspace}\else
+ \hskip\xmllastatt\relax % todo: check for dimension
+ \fi
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:mfenced % {} around separator is needed for spacing
+ \mathml_mfenced{#1}
+\stopxmlsetups
+
+\defineoverlay [mml:enclose:box] [\useMPgraphic{mml:enclose:box}]
+\defineoverlay [mml:enclose:roundedbox] [\useMPgraphic{mml:enclose:roundedbox}]
+\defineoverlay [mml:enclose:circle] [\useMPgraphic{mml:enclose:circle}]
+\defineoverlay [mml:enclose:left] [\useMPgraphic{mml:enclose:left}]
+\defineoverlay [mml:enclose:right] [\useMPgraphic{mml:enclose:right}]
+\defineoverlay [mml:enclose:top] [\useMPgraphic{mml:enclose:top}]
+\defineoverlay [mml:enclose:bottom] [\useMPgraphic{mml:enclose:bottom}]
+\defineoverlay [mml:enclose:updiagonalstrike] [\useMPgraphic{mml:enclose:updiagonalstrike}]
+\defineoverlay [mml:enclose:downdiagonalstrike] [\useMPgraphic{mml:enclose:downdiagonalstrike}]
+\defineoverlay [mml:enclose:horizontalstrike] [\useMPgraphic{mml:enclose:horizontalstrike}]
+\defineoverlay [mml:enclose:verticalstrike] [\useMPgraphic{mml:enclose:verticalstrike}]
+
+\startuseMPgraphic{mml:enclose:box}
+ draw OverlayBox withpen pencircle scaled (ExHeight/10) ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:roundedbox}
+ draw OverlayBox cornered .5ExHeight withpen pencircle scaled (ExHeight/10) ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:circle}
+ draw fullcircle xysized(bbwidth(OverlayBox),bbheight(OverlayBox)) withpen pencircle scaled (ExHeight/10) ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:left}
+ draw leftboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:right}
+ draw rightboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:top}
+ draw topboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:bottom}
+ draw bottomboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:updiagonalstrike}
+ path p ; p := OverlayBox enlarged -.25ExHeight ;
+ draw llcorner p -- urcorner p withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:downdiagonalstrike}
+ path p ; p := OverlayBox enlarged -.25ExHeight ;
+ draw ulcorner p -- lrcorner p withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:horizontalstrike}
+ path p ; p := OverlayBox enlarged -.25ExHeight ;
+ draw .5[llcorner p,ulcorner p] -- .5[lrcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+\startuseMPgraphic{mml:enclose:verticalstrike}
+ path p ; p := OverlayBox enlarged -.25ExHeight ;
+ draw .5[llcorner p,lrcorner p] -- .5[ulcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ;
+ setbounds currentpicture to OverlayBox ;
+\stopuseMPgraphic
+
+\startxmlsetups mml:menclose
+ \edef\mmlmenclosenotation{\mathml_menclosepattern{#1}}
+ \ifempty\mmlmenclosenotation
+ \xmlflush{#1}
+ \else
+ \doifelse \mmlmenclosenotation {mml:enclose:longdiv} {
+ \overline{\left)\strut\xmlflush{#1}\right.}
+ } {
+ \doifelse \mmlmenclosenotation {mml:enclose:actuarial} {
+ \overline{\left.\strut\xmlflush{#1}\right\vert}
+ } {
+ \doifelse \mmlmenclosenotation {mml:enclose:radical} {
+ \sqrt{\xmlflush{#1}}
+ } {
+ % todo: no framed when longdiv, actuarial or radical ? spec ?
+ \vcenter {
+ \framed
+ [frame=off,strut=no,background={\mmlmenclosenotation}] % offset is kind of undefined
+ {
+ \startpickupmath
+ \expanded{\doifelseinset {mml:enclose:longdiv} {\mmlmenclosenotation}} {
+ \overline{\left)\strut\xmlflush{#1}\right.}
+ } {
+ \expanded{\doifelseinset {mml:enclose:actuarial} {\mmlmenclosenotation}} {
+ \overline{\left.\strut\xmlflush{#1}\right\vert}
+ } {
+ \expanded{\doifelseinset {mml:enclose:radical} {\mmlmenclosenotation}} {
+ \sqrt{\xmlflush{#1}}
+ } {
+ \expanded{\doifelseinset {mml:enclose:rule} {\mmlmenclosenotation}} {
+ \overline{\strut\xmlflush{#1}}
+ } {
+ \xmlflush{#1}
+ }
+ }
+ }
+ }
+ \stoppickupmath
+ }
+ }
+ }
+ }
+ }
+ \fi
+\stopxmlsetups
+
+\xmlmapvalue {mml:mfrac:linethickness} {thin} {.2pt}
+\xmlmapvalue {mml:mfrac:linethickness} {medium} {.4pt}
+\xmlmapvalue {mml:mfrac:linethickness} {thick} {.8pt}
+\xmlmapvalue {mml:mfrac:linethickness} {0} {0pt}
+
+\startxmlsetups mml:mfrac % dodo: handle linethickness in lua + unit
+ \begingroup
+ \edef\mmlfraclinethickness{\xmlatt{#1}{linethickness}}
+ \ifempty\mmlfraclinethickness
+ \doifelse{\xmlatt{#1}{bevelled}}{true} {
+ \left.\mmlfirst{#1}\middle/\mmlsecond{#1}\right.% \thinspace\middle/\thinspace
+ } {
+ \mmlfrac{\mmlfirst{#1}}{\mmlsecond{#1}}
+ }
+ \else % use \ifchknum
+ \doifelse {\xmlval{mml:mfrac:linethickness}{\mmlfraclinethickness}{}} {} {
+ \scratchdimen\xmlval{mml:mfrac:linethickness}\mmlfraclinethickness{.4pt}
+ } {
+ % probably not yet ok
+ \setdimensionwithunit\scratchdimen\mmlfraclinethickness{pt}
+ }
+ {
+ {\mmlfirst{#1}}
+ \above\scratchdimen
+ {\mmlsecond{#1}}
+ }
+ \fi
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:ms
+ \hbox {
+ \tf % else encoding problems
+ \ifxmlattempty{#1}{lquote}\symbol[leftquotation]\else\xmllastatt\fi
+ \applymmlsometext{#1}{\xmlflush{#1}}
+ \ifxmlattempty{#1}{rquote}\symbol[rightquotation]\else\xmllastatt\fi
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:mstyle
+ \begingroup
+ \pushmathstyle
+ \setmmlmathstyle{#1}
+ \setmmlscriptlevel{#1}
+ \xmlflush{#1}
+ \popmathstyle
+ \endgroup
+\stopxmlsetups
+
+\setupMMLappearance[text][\c!alternative=\v!b] % a=normal, b=keep spaces
+
+\startxmlsetups mml:mtext
+ \text {
+ \applymmlsometext{#1}{
+ \ifcstok{\MMLtextalternative}\v!a
+ \ignorespaces
+ \xmlflush{#1}
+ \removeunwantedspaces
+ \else
+ \xmlflush{#1}
+ \fi
+ }
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:merror
+ \hbox{\startimath\displaystyle\xmlflush{#1}\stopimath}
+\stopxmlsetups
+
+\startxmlsetups mml:mphantom
+ \phantom{\triggermathstyle\normalmathstyle\ignorespaces\xmlflush{#1}\removeunwantedspaces}
+\stopxmlsetups
+
+\startxmlsetups mml:mpadded % todo
+ \xmlflush{#1}
+\stopxmlsetups
+
+% mrow / option: no fenced
+
+\startxmlsetups mml:maction
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups mml:mrow
+ \begingroup
+ \xmlflush{#1}
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:msqrt
+ \sqrt{\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups mml:mroot
+ \root{\mmlsecond{#1}}\of{\mmlfirst{#1}}
+\stopxmlsetups
+
+\setupMMLappearance[scripts][\c!alternative=\v!a] % {} rond base
+
+% brrr no { } when limop .. todo: better in lua
+% speed up with ifx and setups or just in lua
+
+\let\mmlnucleus\relax
+
+% maybe make helper
+% \iftok{\utfmathclass{\xmlraw{#1}{/mml:*[1]}}}{limop}
+% \ifcstok{\utfmathclass{\xmlraw{#1}{/mml:*[1]}}}\s!limop
+
+\startxmlsetups mml:msub
+ \iftok{\utfmathclass{\xmlraw{#1}{/mml:*[1]}}}{limop}
+ \mmlfirst{#1}
+ \normalsubscript{\mmlsecond{#1}}
+ \orelse\ifcstok{\MMLscriptsalternative}\v!a
+ {\mmlfirst{#1}}
+ \normalsubscript{\mmlsecond{#1}}
+ \else
+ \mmlfirst{#1}
+ \normalsubscript{\mmlsecond{#1}}
+ \fi
+\stopxmlsetups
+
+\startxmlsetups mml:msup
+ \iftok{\utfmathclass{\xmlraw{#1}{/mml:*[1]}}}{limop}
+ \mmlfirst{#1}
+ \normalsuperscript{\mmlsecond{#1}}
+ \orelse\ifcstok{\MMLscriptsalternative}\v!a
+ {\mmlfirst{#1}}
+ \normalsuperscript{\mmlsecond{#1}}
+ \else
+ \mmlfirst{#1}
+ \normalsuperscript{\mmlsecond{#1}}
+ \fi
+\stopxmlsetups
+
+% use mathclass number
+
+\startxmlsetups mml:msubsup
+ \iftok{\utfmathclass{\xmlraw{#1}{/mml:*[1]}}}{limop}
+ \mmlfirst{#1}
+ \normalsubscript{\mmlsecond{#1}}
+ \normalsuperscript{\mmlthird{#1}}
+ \orelse\ifcstok{\MMLscriptsalternative}\v!a
+ {\mmlfirst{#1}}
+ \normalsubscript{\mmlsecond{#1}}
+ \normalsuperscript{\mmlthird {#1}}
+ \else
+ \mmlfirst{#1}
+ \normalsubscript{\mmlsecond{#1}}
+ \normalsuperscript{\mmlthird {#1}}
+ \fi
+\stopxmlsetups
+
+% helpers
+
+\protected\def\mmlexecutecommand#1%
+ {\ifcsname#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi
+ \lastnamedcs}
+
+\let\mmlextensible\mathml_extensible
+
+\definemathtriplet [\v!mathematics] [mmlovertriplet] % or will we use a special instance
+\definemathtriplet [\v!mathematics] [mmlundertriplet] % or will we use a special instance
+\definemathtriplet [\v!mathematics] [mmldoubletriplet] % or will we use a special instance
+
+% common to munder/mover/munderover : will become core helper (speed up too)
+
+\starttexdefinition protected mmlfencedfirst #1
+ \xmlelement{#1}{1}
+\stoptexdefinition
+\starttexdefinition protected mmlfencedsecond #1
+ \xmlelement{#1}{2}
+\stoptexdefinition
+\starttexdefinition protected mmlfencedthird #1
+ \xmlelement{#1}{3}
+\stoptexdefinition
+
+% mover
+
+\starttexdefinition protected mmloverabove #1
+ \mmlexecutecommand{\utfmathfiller\mmlovertoken} {\mmlfencedsecond{#1}} \relax
+\stoptexdefinition
+\starttexdefinition protected mmloverbase #1
+ \mmlexecutecommand{\utfmathfiller\mmlbasetoken} {\mmlfencedfirst{#1}} \relax
+\stoptexdefinition
+\starttexdefinition protected mmloverbasefiller #1
+ \mmlexecutecommand{e\utfmathcommandfiller\mmlbasetoken} \relax {\mmlfencedsecond{#1}} {}
+\stoptexdefinition
+\starttexdefinition protected mmloveraccent #1
+ \mmlexecutecommand{\utfmathcommandabove\mmlovertoken} \relax {\mmlfencedfirst{#1}}
+\stoptexdefinition
+
+\starttexdefinition protected mmlovertext #1
+ \mmlovertriplet {\mmloverbase{#1}} {\mmloverabove{#1}} {}
+\stoptexdefinition
+\starttexdefinition protected mmloveraccentchecker #1
+ \edef\mmlovertoken{\mmlextensible{\xmlraw{#1}{/mml:*[2]}}}% /text()
+ \doifelseutfmathabove\mmlovertoken \mmloveraccent \mmlovertext {#1}
+\stoptexdefinition
+
+\startxmlsetups mml:mover
+ \edef\mmlbasetoken{\mmlextensible{\xmlraw{#1}{/mml:*[1]}}}% /text()
+ \doifelseutfmathlimop\mmlbasetoken
+ {\mmllimopover{#1}}
+ {\doifelseutfmathfiller\mmlbasetoken \mmloverbasefiller \mmloveraccentchecker {#1}}
+\stopxmlsetups
+
+\starttexdefinition mmllimopover #1
+ \mmlbasetoken\normalsuperscript{\mmlfencedsecond{#1}}
+\stoptexdefinition
+
+% munder
+
+\starttexdefinition protected mmlunderbelow #1
+ \mmlexecutecommand{\utfmathfiller\mmlundertoken} {\mmlfencedsecond{#1}} \relax
+\stoptexdefinition
+\starttexdefinition protected mmlunderbase #1
+ \mmlexecutecommand{\utfmathfiller\mmlbasetoken} {\mmlfencedfirst{#1}} \relax
+\stoptexdefinition
+\starttexdefinition protected mmlunderbasefiller #1
+ \mmlexecutecommand{e\utfmathcommandfiller\mmlbasetoken} \relax {} {\mmlfencedsecond{#1}}
+\stoptexdefinition
+\starttexdefinition protected mmlunderaccent #1
+ \mmlexecutecommand{\utfmathcommandbelow\mmlundertoken} \relax {\mmlfencedfirst{#1}}
+\stoptexdefinition
+
+\starttexdefinition protected mmlundertext #1
+ \mmlundertriplet {\mmlunderbase{#1}} {} {\mmlunderbelow{#1}}
+\stoptexdefinition
+\starttexdefinition protected mmlunderaccentchecker #1
+ \edef\mmlundertoken{\mmlextensible{\xmlraw{#1}{/mml:*[2]}}}% /text()
+ \doifelseutfmathbelow\mmlundertoken \mmlunderaccent \mmlundertext {#1}
+\stoptexdefinition
+
+\startxmlsetups mml:munder
+ \edef\mmlbasetoken{\mmlextensible{\xmlraw{#1}{/mml:*[1]}}}% /text()
+ \doifelseutfmathlimop\mmlbasetoken
+ {\mmllimopunder{#1}}
+ {\doifelseutfmathfiller\mmlbasetoken \mmlunderbasefiller \mmlunderaccentchecker {#1}}
+\stopxmlsetups
+
+\starttexdefinition mmllimopunder #1
+ \mmlbasetoken\normalsubscript{\mmlfencedsecond{#1}}
+\stoptexdefinition
+
+% munderover
+
+\starttexdefinition protected mmlunderoveraccentcheckerUO #1
+ \edef\mmlundercommand{\utfmathcommandbelow\mmlundertoken}
+ \edef\mmlovercommand {\utfmathcommandabove\mmlovertoken}
+ \edef\mmlbasecommand {\mmlovercommand\mmlundercommand}
+ \ifcsname\mmlbasecommand\endcsname
+ \lastnamedcs {\mmlfencedfirst{#1}}
+ \orelse\ifcsname\mmlundercommand\endcsname
+ \ifcsname\mmlovercommand\endcsname
+ \lastnamedcs {\csname\mmlundercommand\endcsname{\mmlfencedfirst{#1}}}
+ \else
+ \mmldoubletriplet {\csname\mmlundercommand\endcsname{\mmlfencedfirst{#1}}} {\mmlfencedthird{#1}\mmlfencedthird{#1}} {}
+ \fi
+ \orelse\ifcsname\mmlovercommand\endcsname
+ \mmldoubletriplet {\csname\mmlovercommand\endcsname{\mmlfencedfirst{#1}}} {} {\mmlfencedsecond{#1}}
+ \else
+ \mmlunderoveraccentcheckerTT {#1}
+ \fi
+\stoptexdefinition
+\starttexdefinition protected mmlunderoveraccentcheckerUT #1
+ \edef\mmlundercommand{\utfmathcommandbelow\mmlundertoken}
+ \edef\mmlbasecommand {\mmlundercommand text}
+ \ifcsname\mmlbasecommand\endcsname
+ \lastnamedcs {\mmlfencedfirst{#1}} {\mmlfencedthird{#1}}
+ \orelse\ifcsname\mmlundercommand\endcsname
+ \mmldoubletriplet {\csname\mmlundercommand\endcsname{\mmlfencedfirst{#1}}} {\mmlfencedthird{#1}} {}
+ \else
+ \mmlunderoveraccentcheckerTT {#1}
+ \fi
+\stoptexdefinition
+\starttexdefinition protected mmlunderoveraccentcheckerOT #1
+ \edef\mmlovercommand{\utfmathcommandabove\mmlovertoken}
+ \edef\mmlbasecommand{\mmlovercommand text}
+ \ifcsname\mmlbasecommand\endcsname
+ \lastnamedcs {\mmlfencedfirst{#1}} {\mmlfencedsecond{#1}}
+ \orelse\ifcsname\mmlovercommand\endcsname
+ \mmldoubletriplet {\csname\mmlovercommand\endcsname{\mmlfencedfirst{#1}}} {} {\mmlfencedsecond{#1}}
+ \else
+ \mmlunderoveraccentcheckerTT {#1}
+ \fi
+\stoptexdefinition
+\starttexdefinition protected mmlunderoveraccentcheckerTT #1
+ \mmldoubletriplet {\mmlfencedfirst{#1}} {\mmlfencedthird{#1}} {\mmlfencedsecond{#1}} \relax
+\stoptexdefinition
+\starttexdefinition protected mmlunderoveraccentchecker #1
+ \edef\mmlundertoken{\mmlextensible{\xmlraw{#1}{/mml:*[2]}}}% /text()
+ \edef\mmlovertoken {\mmlextensible{\xmlraw{#1}{/mml:*[3]}}}% /text()
+ \doifelseutfmathbelow\mmlundertoken {
+ \doifelseutfmathabove\mmlovertoken \mmlunderoveraccentcheckerUO \mmlunderoveraccentcheckerUT {#1}
+ } {
+ \doifelseutfmathabove\mmlovertoken \mmlunderoveraccentcheckerOT \mmlunderoveraccentcheckerTT {#1}
+ }
+\stoptexdefinition
+
+\starttexdefinition protected mmlunderoverbasefiller #1
+ \mmlexecutecommand{e\utfmathcommandfiller\mmlbasetoken} \relax {\mmlfencedthird{#1}} {\mmlfencedsecond{#1}}
+\stoptexdefinition
+
+\startxmlsetups mml:munderover
+ \edef\mmlbasetoken{\mmlextensible{\xmlraw{#1}{/mml:*[1]}}}% /text()
+ \doifelseutfmathlimop\mmlbasetoken
+ {\mmllimopunderover{#1}}
+ {\doifelseutfmathfiller\mmlbasetoken \mmlunderoverbasefiller \mmlunderoveraccentchecker {#1}}
+\stopxmlsetups
+
+\starttexdefinition mmllimopunderover #1
+ \mmlbasetoken\normalsuperscript{\mmlfencedthird{#1}}\normalsubscript{\mmlfencedsecond{#1}}
+\stoptexdefinition
+
+% tables (mml:mtable, mml:mtr, mml:mlabledtr, mml:mtd)
+
+\startxmlsetups mml:mtable % some more attributes need to be supported
+ \vcenter {
+ \hbox {% needed because otherwise positions make the vcenter wide
+ \mathml_mtable{#1}
+ }
+ }
+\stopxmlsetups
+
+\startxmlsetups mml:mcolumn
+ \vbox{\mathml_mcolumn{#1}}% needs checking
+\stopxmlsetups
+
+\def\mmlsetfakewidth#1{\setbox\scratchbox\hbox{#1}\scratchdimen\wd\scratchbox}
+
+\def\mmlmcolumndigitspace {\mmlsetfakewidth {0}\kern\scratchdimen}
+\def\mmlmcolumndigitrule {\mmlsetfakewidth {0}\vrule \s!width \scratchdimen \s!height .2\points \s!depth .2\points\relax}
+\def\mmlmcolumnsymbolrule {\mmlsetfakewidth{\times}\vrule \s!width \scratchdimen \s!height .2\points \s!depth .2\points\relax}
+\def\mmlmcolumnpunctuationrule{\mmlsetfakewidth {.}\vrule \s!width \scratchdimen \s!height .2\points \s!depth .2\points\relax}
+
+\setupMMLappearance[mspace][\c!option=] % \v!test
+
+\startxmlsetups mml:mspace
+ \begingroup
+ \edef\mmlspacetext{\xmlatt{#1}{spacing}}
+ \ifempty\mmlspacetext
+ \scratchwidth \xmlattdef{#1}{width} \!!zeropoint % must be string
+ \scratchheight\xmlattdef{#1}{height}\!!zeropoint
+ \scratchdepth \xmlattdef{#1}{depth} \!!zeropoint
+ \ifdim\scratchheight=\zeropoint
+ \ifdim\scratchdepth=\zeropoint\else
+ \novrule\s!depth\scratchdepth\s!height\zeropoint\s!width\zeropoint
+ \fi
+ \else
+ \novrule\s!depth\zeropoint\s!height\scratchheight\s!width\zeropoint
+ \fi
+ \ifdim\scratchwidth=\zeropoint
+ \orelse\ifx\MMLmspaceoption\v!test
+ \hbox to \scratchwidth{\showstruts\strut\hss\lower2\exheight\hbox{\infofont\xmlattdef{#1}{width}}\hss\strut}
+ \else
+ \hskip\scratchwidth
+ \fi
+ \orelse\ifx\MMLmspaceoption\v!test
+ \hbox{\showstruts\strut\phantom{\triggermathstyle\normalmathstyle\mmlspacetext}\strut}
+ \else
+ \phantom{\triggermathstyle\normalmathstyle\mmlspacetext}
+ \fi
+ \endgroup
+\stopxmlsetups
+
+% later we can do a better job by manipulating node lists
+
+% \startxmlsetups mml:mline
+% % new, rather undefined, we need to capture a few keywords
+% \edef\mmllinewidth {\xmlatt{#1}{linethickness}}
+% \edef\mmllinetext {\xmlatt{#1}{spacing}}
+% \edef\mmllinelength{\xmlattdef{#1}{length}\!!zeropoint}
+% \ifempty\mmllinewidth
+% \!!deptha.5\linewidth
+% \else
+% \!!deptha.5\dimexpr\mmllinewidth\relax
+% \fi
+% \!!heighta\!!deptha
+% \ifempty\mmllinetext
+% \ifempty\mmllinelength
+% \!!widtha\zeropoint
+% \else
+% \!!widtha\mmllinelength
+% \fi
+% \else
+% \setbox\scratchbox\hbox{\mathematics{\mathstyle{\mmllinetext}}}% not ok
+% \!!widtha\wd\scratchbox
+% \fi
+% \hbox{\vrule\s!width\!!widtha\s!depth\!!deptha\s!height\!!heighta}
+% \stopxmlsetups
+
+\startxmlsetups mml:mglyph % probably never ok (hbox is needed in order to switch to normal font)
+ \begingroup
+ \edef\mmlglyphfontfamily{\xmlatt {#1}{fontfamily}}
+ \edef\mmlglyphalt {\xmlattdef{#1}{alt}{unknown}}
+ \edef\mmlglyphindex {\xmlatt {#1}{index}}
+ \ifempty\mmlglyphfontfamily
+ \hbox{\tttf[no fontfamily specified for \mmlglyphalt]}
+ \orelse\ifempty\mmlglyphindex
+ \hbox{\tttf[no index specified for \mmlglyphalt]}
+ \else
+ \hbox{\getglyph\mmlglyphfontfamily\mmlglyphindex}
+ \fi
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups mml:maligngroup \stopxmlsetups % will be done when needed
+\startxmlsetups mml:malignmark \stopxmlsetups % will be done when needed
+
+\startxmlsetups mml:none \stopxmlsetups
+\startxmlsetups mml:mprescripts \stopxmlsetups
+
+\startxmlsetups mml:mmultiscripts
+ \mathml_mmultiscripts{#1}
+\stopxmlsetups
+
+% goodie
+
+\definebuffer[mml]
+
+\permanent\protected\def\stopmml{\xmlprocessbuffer{@mml@}{\thedefinedbuffer{mml}}{}}
+
+\stopmodule
+
+\protect \endinput
+
+% TODO:
+%
+% <apply><divide/>
+% <apply><minus/>
+% <apply><minus/><ci>b</ci></apply>
+% <apply><minus/><ci>b</ci></apply>
+% <apply><root/> <ci>a</ci></apply>
+% </apply>
+% <apply><minus/>
+% <apply><minus/><ci>b</ci><ci>b</ci></apply>
+% <apply><minus/><ci>b</ci></apply>
+% <apply><root/> <ci>a</ci></apply>
+% </apply>
+% </apply>