diff options
Diffstat (limited to 'tex')
43 files changed, 3452 insertions, 71 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index aac7ad364..6671dcdd1 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2021.06.04 17:20} +\newcontextversion{2021.06.07 08:05} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index b0041b657..f22901bf5 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2021.06.04 17:20} +\edef\contextversion{2021.06.07 08:05} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-nl.mkii b/tex/context/base/mkii/mult-nl.mkii index ce87e0b93..78445f695 100644 --- a/tex/context/base/mkii/mult-nl.mkii +++ b/tex/context/base/mkii/mult-nl.mkii @@ -1265,6 +1265,7 @@ \setinterfaceconstant{symbolset}{symboolset} \setinterfaceconstant{symcolor}{symkleur} \setinterfaceconstant{symstyle}{symletter} +\setinterfaceconstant{synchronize}{synchronize} \setinterfaceconstant{synonym}{synoniem} \setinterfaceconstant{synonymcolor}{synoniemkleur} \setinterfaceconstant{synonymcommand}{synoniemcommando} diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua index 10d87e139..f95ac301c 100644 --- a/tex/context/base/mkiv/cldf-ini.lua +++ b/tex/context/base/mkiv/cldf-ini.lua @@ -20,16 +20,8 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- more efficient approach is stable enough to move the original code to the obsolete -- module. -- --- to be considered: --- --- 0.528 local foo = tex.ctxcatcodes --- 0.651 local foo = getcount("ctxcatcodes") --- 0.408 local foo = getcount(ctxcatcodes) -- local ctxcatcodes = tex.iscount("ctxcatcodes") - -- maybe: (escape) or 0x2061 (apply function) or 0x2394 (software function ⎔) (old) -- note : tex.print == line with endlinechar appended --- todo : context("%bold{total: }%s",total) --- todo : context.documentvariable("title") -- -- During the crited project we ran into the situation that luajittex was 10-20 times -- slower that luatex ... after 3 days of testing and probing we finally figured out that diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index d4815dd08..2b0da3435 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.06.04 17:20} +\newcontextversion{2021.06.07 08:05} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context-todo.tex b/tex/context/base/mkiv/context-todo.tex index 6aa5bca08..e9345c409 100644 --- a/tex/context/base/mkiv/context-todo.tex +++ b/tex/context/base/mkiv/context-todo.tex @@ -169,6 +169,11 @@ concern \LUATEX\ have been removed from the agenda but some improvements in \stopitem \stopitemize +% should be in lpdf namespace: +% +% ./grph-pat.lua 69: local l = new_literal(lpdf.patternstream(p,width,height)) + + \stopsubject \stoptext diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index ac9434b86..b6e4c672d 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2021.06.04 17:20} +\edef\contextversion{2021.06.07 08:05} %D Kind of special: diff --git a/tex/context/base/mkiv/grph-pat.lua b/tex/context/base/mkiv/grph-pat.lua index 4310af672..7954e9fee 100644 --- a/tex/context/base/mkiv/grph-pat.lua +++ b/tex/context/base/mkiv/grph-pat.lua @@ -9,7 +9,8 @@ if not modules then modules = { } end modules ['grph-pat'] = { -- This is just a proof of concept. Viewers behave different (offsets) and Acrobat doesn't -- show xform based patterns. -- --- This module will be cleaned up and use codeinjections and such. +-- This module will be cleaned up and use codeinjections and such. It should be in the lpdf +-- namespace. local texsetbox = tex.setbox local texgetbox = tex.getbox diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua index 2745fb52a..13ebb8fcb 100644 --- a/tex/context/base/mkiv/mult-low.lua +++ b/tex/context/base/mkiv/mult-low.lua @@ -227,7 +227,7 @@ return { -- "doglobal", "dodoglobal", "redoglobal", "resetglobal", -- - "donothing", "dontcomplain", "forgetall", + "donothing", "untraceddonothing", "dontcomplain", "forgetall", -- "donetrue", "donefalse", "foundtrue", "foundfalse", -- diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index e7eb8dde4..a3e2f2115 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -319,6 +319,7 @@ return { "gleaders", "glet", "gletcsname", + "glettonothing", "gluespecdef", "glyphdatafield", "glyphoptions", @@ -392,6 +393,7 @@ return { "letcsname", "letfrozen", "letprotected", + "lettonothing", "linedirection", "linepar", "localbrokenpenalty", diff --git a/tex/context/base/mkiv/s-inf-01-pdf-keep.pdf b/tex/context/base/mkiv/s-inf-01-pdf-keep.pdf Binary files differdeleted file mode 100644 index 0002d614e..000000000 --- a/tex/context/base/mkiv/s-inf-01-pdf-keep.pdf +++ /dev/null diff --git a/tex/context/base/mkiv/s-inf-03-pdf-keep.pdf b/tex/context/base/mkiv/s-inf-03-pdf-keep.pdf Binary files differdeleted file mode 100644 index b037b49ab..000000000 --- a/tex/context/base/mkiv/s-inf-03-pdf-keep.pdf +++ /dev/null diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 0002d614e..ce6002720 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex b037b49ab..bc07c3a2b 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkxl/anch-pos.mkxl b/tex/context/base/mkxl/anch-pos.mkxl index d217f2cac..6b482dc05 100644 --- a/tex/context/base/mkxl/anch-pos.mkxl +++ b/tex/context/base/mkxl/anch-pos.mkxl @@ -406,7 +406,7 @@ \permanent\let\disableparpositions\relax -\aliased\let\registerparoptions\relax +\permanent\lettonothing\registerparoptions % hooks into everypar \permanent\protected\def\doregisterparoptions {\iftrialtypesetting \orelse\ifinpagebody \orelse\ifmmode \orelse\ifinformula \else diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 05c0fc8b2..79bb909ab 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.06.04 17:20} +\newcontextversion{2021.06.07 08:05} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index bbd67d48b..ccd340d28 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.06.04 17:20} +\immutable\edef\contextversion{2021.06.07 08:05} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/driv-ini.lmt b/tex/context/base/mkxl/driv-ini.lmt index 729196e87..40b351d84 100644 --- a/tex/context/base/mkxl/driv-ini.lmt +++ b/tex/context/base/mkxl/driv-ini.lmt @@ -316,7 +316,7 @@ do local filename = nil drivers.install { - name = "default", + name = "default", -- "pdf" actions = { convert = drivers.converters.engine, outputfilename = function(driver) diff --git a/tex/context/base/mkxl/font-fmp.lmt b/tex/context/base/mkxl/font-fmp.lmt index f35c96f49..dc70a70e8 100644 --- a/tex/context/base/mkxl/font-fmp.lmt +++ b/tex/context/base/mkxl/font-fmp.lmt @@ -8,8 +8,13 @@ if not modules then modules = { } end modules ['font-fmp'] = { -- We only need to pick up the filename and optionally the enc file as we only use -- them for old school virtual math fonts. We might as well drop this completely. --- This used to be a backend module but the code is rather generic so we just put it --- here now. +-- This used to be a backend module but the code is rather generic so for now we +-- just put it here. +-- +-- As Type 1 is kind of obsolete I don't expect usage of those fonts in ways that +-- are not yet covered. Actually, we don't need map files at all because we read the +-- afm files. Maybe for math but there at some point we'll ditch the virtual old +-- school variants because afaik ConTeXt users are not using these any longer. local find, match, splitlines = string.find, string.match, string.splitlines @@ -99,7 +104,10 @@ function mappings.loadline(how,line) end function mappings.reset() - lpdf.setmapfile("") -- tricky ... backend related + local setmapfile = lpdf and lpdf.setmapfile + if setmapfile then + setmapfile("") -- tricky ... backend related + end end mappings.getentry = getentry diff --git a/tex/context/base/mkxl/node-ref.lmt b/tex/context/base/mkxl/node-ref.lmt index 78ff824c9..a7b624591 100644 --- a/tex/context/base/mkxl/node-ref.lmt +++ b/tex/context/base/mkxl/node-ref.lmt @@ -100,7 +100,9 @@ local dir_code = nodecodes.dir local par_code = nodecodes.par local leftskip_code = gluecodes.leftskip +local lefthang_code = gluecodes.lefthangskip local rightskip_code = gluecodes.rightskip +local righthang_code = gluecodes.righthangskip local parfillleftskip_code = gluecodes.parfillleftskip local parfillskip_code = gluecodes.parfillskip @@ -359,9 +361,9 @@ local inject_areas do goto NEXT elseif id == glue_code then local subtype = getsubtype(current) - if subtype == leftskip_code or subtype == parfillleftskip_code then + if subtype == leftskip_code or subtype == lefthang_code or subtype == parfillleftskip_code then goto NEXT - elseif subtype == rightskip_code or subtype == parfillskip_code then + elseif subtype == rightskip_code or subtype == righthang_code or subtype == parfillskip_code then if reference and (done[reference] or 0) == 0 then head, current = inject_range(head,first,last,reference,parent,pardir,firstdir) reference = nil diff --git a/tex/context/base/mkxl/page-par.mkxl b/tex/context/base/mkxl/page-par.mkxl index c198784dc..4cfc3f9bf 100644 --- a/tex/context/base/mkxl/page-par.mkxl +++ b/tex/context/base/mkxl/page-par.mkxl @@ -22,7 +22,7 @@ \definecounter[\v!paragraph] -\permanent\let\showparagraphnumber\relax +\permanent\lettonothing\showparagraphnumber \appendtoks \page_par_check_state @@ -36,16 +36,16 @@ \lastnamedcs \fi} -\setvalue{\??paragraphnumberingvariants\v!start}% +\defcsname\??paragraphnumberingvariants\v!start\endcsname {\enforced\let\showparagraphnumber\page_par_show_number_normal} -\setvalue{\??paragraphnumberingvariants\v!stop}% - {\enforced\let\showparagraphnumber\relax} +\defcsname\??paragraphnumberingvariants\v!stop\endcsname + {\enforced\lettonothing\showparagraphnumber} -\setvalue{\??paragraphnumberingvariants\v!line}% +\defcsname\??paragraphnumberingvariants\v!line\endcsname {\enforced\let\showparagraphnumber\page_par_show_number_lines} -\setvalue{\??paragraphnumberingvariants\v!reset}% +\defcsname\??paragraphnumberingvariants\v!reset\endcsname {\strc_counters_reset\v!paragraph \enforced\let\showparagraphnumber\page_par_show_number_normal} diff --git a/tex/context/base/mkxl/spac-par.mkxl b/tex/context/base/mkxl/spac-par.mkxl index 66b08633d..6c3927861 100644 --- a/tex/context/base/mkxl/spac-par.mkxl +++ b/tex/context/base/mkxl/spac-par.mkxl @@ -104,7 +104,7 @@ \installcorenamespace {parwrapafter} \installcorenamespace {parwrapcount} -\let\spac_paragraph_wrap\relax +\lettonothing\spac_paragraph_wrap \newcount\c_spac_paragraph_group_level @@ -147,7 +147,7 @@ \clf_setparwrapper{#3}#4}% #2\csname\??parwrapafter #3\endcsname{#5}% \clf_newparwrapper{#3}% - \enforced\let\spac_paragraph_wrap\spac_paragraph_update} + \let\spac_paragraph_wrap\spac_paragraph_update} \def\spac_register_par_wrapper_nop#1#2#3#4#5% {\ifcsname\??parwrapcount#3\endcsname \else @@ -212,7 +212,7 @@ \setparagraphfreezing -\appendtoks\enforced\let\spac_paragraph_wrap\relax\to\everyforgetall +\appendtoks\lettonothing\spac_paragraph_wrap\to\everyforgetall %D In due time, the code below will be upgraded using the above mechanisms. @@ -250,8 +250,6 @@ \installcorenamespace{paragraphintro} -\let\spac_paragraphs_flush_intro\relax % hook into everypar - \newtoks\t_spac_paragraphs_intro_first \newtoks\t_spac_paragraphs_intro_next \newtoks\t_spac_paragraphs_intro_each @@ -260,8 +258,8 @@ \newconditional\c_spac_paragraphs_intro_next \newconditional\c_spac_paragraphs_intro_each -\let\spac_paragraphs_flush_intro\relax -\let\spac_paragraphs_intro_step \relax +\lettonothing\spac_paragraphs_flush_intro +\lettonothing\spac_paragraphs_intro_step \permanent\protected\tolerant\def\setupparagraphintro[#1]#*[#2]% {\def\spac_paragraphs_intro_step##1% @@ -277,7 +275,7 @@ \global\t_spac_paragraphs_intro_first\emptytoks \global\t_spac_paragraphs_intro_next \emptytoks \global\t_spac_paragraphs_intro_each \emptytoks - \glet\spac_paragraphs_flush_intro\relax} + \glettonothing\spac_paragraphs_flush_intro} \defcsname\??paragraphintro\v!first\endcsname#1% {\global\settrue\c_spac_paragraphs_intro_first @@ -372,7 +370,7 @@ \the\t_spac_paragraphs_intro_next \the\t_spac_paragraphs_intro_each \else - \glet\spac_paragraphs_flush_intro\relax + \glettonothing\spac_paragraphs_flush_intro \the\t_spac_paragraphs_intro_next \fi}} @@ -385,7 +383,7 @@ %D This macro collects data that will be flushed at the next paragraph. By using %D this macro you can avoid interfering nodes (writes, etc). -\aliased\let\flushpostponednodedata\relax % hook into everypar +\lettonothing\flushpostponednodedata % hook into everypar \newbox \b_spac_postponed_data %newcount\c_spac_postponed_data @@ -453,7 +451,7 @@ \ifvoid\b_spac_postponed_data\else \hpack{\smashedbox\b_spac_postponed_data}% \box\b_spac_postponed_data \fi - \enforced\glet\flushpostponednodedata\relax + \enforced\glettonothing\flushpostponednodedata }%\fi} \permanent\protected\def\doflushatpar % might be renamed diff --git a/tex/context/base/mkxl/spac-ver.mkxl b/tex/context/base/mkxl/spac-ver.mkxl index d11611339..1e630c5bf 100644 --- a/tex/context/base/mkxl/spac-ver.mkxl +++ b/tex/context/base/mkxl/spac-ver.mkxl @@ -1356,10 +1356,10 @@ \newcount\c_spac_keep_lines_together -\aliased\let\restoreinterlinepenalty\relax +\permanent\lettonothing\restoreinterlinepenalty \protected\def\spac_penalties_restore - {\global\enforced\let\restoreinterlinepenalty\relax + {\enforced\glettonothing\restoreinterlinepenalty \overloaded\global\resetpenalties\interlinepenalties \global\c_spac_keep_lines_together\zerocount} diff --git a/tex/context/base/mkxl/strc-not.mklx b/tex/context/base/mkxl/strc-not.mklx index 3faf7135b..a0691d9f1 100644 --- a/tex/context/base/mkxl/strc-not.mklx +++ b/tex/context/base/mkxl/strc-not.mklx @@ -1287,8 +1287,8 @@ \fi} \appendtoks - \enforced\let\flushnotes \relax - \enforced\let\postponenotes\relax + \enforced\lettonothing\flushnotes + \enforced\lettonothing\postponenotes \forgetall \resetallattributes % new, we don't want color bleed into notes \inheritmaintextcolor % but we do want to obey the textcolor @@ -1517,7 +1517,7 @@ \fi \fi} -\aliased\let\flushnotes\relax +\permanent\lettonothing\flushnotes % also \ifcase\insertionmigrationmode here, needs testing: @@ -1534,8 +1534,8 @@ \permanent\protected\def\doflushnotes {\ifconditional\postponingnotes \begingroup - \enforced\let\flushnotes \relax - \enforced\let\postponenotes\relax + \enforced\lettonothing\flushnotes + \enforced\lettonothing\postponenotes \ifconditional\postponednote \ifhmode % needed for tagging ... otherwise we get some weird node free error @@ -1545,7 +1545,7 @@ \clf_flushpostponednotes% this also resets the states ! \global\setfalse\postponednote \global\setfalse\postponingnotes - \enforced\glet\flushnotes\relax + \enforced\glettonothing\flushnotes \endgroup \fi} @@ -1563,8 +1563,8 @@ \newtoks\everyplacelocalnotes \appendtoks - \enforced\let\flushnotes \relax - \enforced\let\postponenotes\relax + \enforced\lettonothing\flushnotes + \enforced\lettonothing\postponenotes \to \everyplacelocalnotes \newconditional\inlocalnotes diff --git a/tex/context/base/mkxl/syst-aux.mkxl b/tex/context/base/mkxl/syst-aux.mkxl index 21b1a66ef..fea524bee 100644 --- a/tex/context/base/mkxl/syst-aux.mkxl +++ b/tex/context/base/mkxl/syst-aux.mkxl @@ -216,7 +216,17 @@ %D Reserved macros for tests: -\aliased\let\donothing\empty +%D A \type \type {\let} is more efficient than a \type {\def} so we often let something +%D to relax or do nothing. However, we then loose the name in tracing. For that we now +%D have \type {\lettonothing \foo} which is efficient but also keeps the name. Of course +%D this is no solution for commands that take arguments but at least it helps tracing a +%D bit. We keep of course \type {\donothing}. + +%D Maybe even nicer is a let that aliases but keeps the name. + +% \aliased\let\donothing\empty + \immutable\def\donothing {} % better in tracing +%untraced\immutable\def\untraceddonothing{} \let\m_syst_string_one \empty \let\m_syst_string_two \empty diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl index d147e07aa..d87277657 100644 --- a/tex/context/base/mkxl/syst-ini.mkxl +++ b/tex/context/base/mkxl/syst-ini.mkxl @@ -681,8 +681,8 @@ \permanent\protected\def\tracingall {\tracingonline \plusone - \tracingcommands \plusthree - \tracingmacros \plustwo + \tracingcommands \plusfour % > 3: show mode change independent + \tracingmacros \plusthree % > 2: obey \untraced \tracingoutput \plusone \tracingpages \plusone \tracingparagraphs\plusone diff --git a/tex/context/base/mkxl/typo-cap.mkxl b/tex/context/base/mkxl/typo-cap.mkxl index afdefe923..744b09a47 100644 --- a/tex/context/base/mkxl/typo-cap.mkxl +++ b/tex/context/base/mkxl/typo-cap.mkxl @@ -249,8 +249,9 @@ \definefont [MixedCaps] -% [CurrentFont*default cp 1.2\exheight] - [CurrentFont*default sa .8] % better adaptation to slanted + [CurrentFont*default cp 1.2\exheight] +% [CurrentFont*default at 1.5\exheight] % better adaptation to slanted but still not nice +% [CurrentFont*default ht 1.2\exheight] % maybe this is better indeed \setupcapitals [\v!mixed] diff --git a/tex/context/base/mkxl/typo-del.mkxl b/tex/context/base/mkxl/typo-del.mkxl index 8e17ea82b..4b8540368 100644 --- a/tex/context/base/mkxl/typo-del.mkxl +++ b/tex/context/base/mkxl/typo-del.mkxl @@ -379,9 +379,9 @@ \appendtoks \expandafter\newcount\csname\??delimitedtextlevel\currentdelimitedtext\endcsname - \frozen\instance\setuevalue{\currentdelimitedtext }{\delimitedtext[\currentdelimitedtext]}% - \frozen\instance\setuevalue{\e!start\currentdelimitedtext}{\startdelimitedtext[\currentdelimitedtext]}% - \frozen\instance\setuevalue{\e!stop \currentdelimitedtext}{\stopdelimitedtext}% + \frozen\instance\protected\edefcsname\currentdelimitedtext \endcsname{\delimitedtext[\currentdelimitedtext]}% + \frozen\instance\protected\edefcsname\e!start\currentdelimitedtext\endcsname{\startdelimitedtext[\currentdelimitedtext]}% + \frozen\instance\protected\edefcsname\e!stop \currentdelimitedtext\endcsname{\stopdelimitedtext}% \to \everydefinedelimitedtext \setupdelimitedtext @@ -407,7 +407,7 @@ \typo_delimited_handle_middle\c!middle \fi} -\let\typo_delimited_repeat\relax +\lettonothing\typo_delimited_repeat \permanent\tolerant\protected\def\startdelimitedtext[#1]#*[#2]% {\begingroup @@ -437,7 +437,7 @@ \ifx\p_delimited_repeat\v!yes \let\typo_delimited_repeat\typo_delimited_repeat_indeed \else - \let\typo_delimited_repeat\relax + \lettonothing\typo_delimited_repeat \fi \setfalse\c_typo_delimited_repeating \edef\p_delimited_location{\delimitedtextparameter\c!location}% @@ -847,7 +847,8 @@ {\dontleavehmode \begingroup \dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext - \usedlanguageparameter{\c!left\currentparentdelimitedtext}% was: \currentdelimitedtext + % \usedlanguageparameter{\c!left\currentparentdelimitedtext}% was: \currentdelimitedtext + \usedlanguageparameter{\c!left\currentparentdelimitedtextparent}% was: \currentdelimitedtext \usedelimitedtextstyleandcolor\c!style\c!color \typo_delimited_start_content \bgroup @@ -856,7 +857,8 @@ \def\typo_delimited_fontdriven_e {\typo_delimited_stop_content - \usedlanguageparameter{\c!right\currentparentdelimitedtext}% was: \currentdelimitedtext + % \usedlanguageparameter{\c!right\currentparentdelimitedtext}% was: \currentdelimitedtext + \usedlanguageparameter{\c!right\currendelimitedtextparent}% was: \currentdelimitedtext \dostoptagged \typo_delimited_pop \endgroup} diff --git a/tex/context/base/mkxl/typo-drp.mkxl b/tex/context/base/mkxl/typo-drp.mkxl index 35bbbca8c..da11f76e7 100644 --- a/tex/context/base/mkxl/typo-drp.mkxl +++ b/tex/context/base/mkxl/typo-drp.mkxl @@ -71,10 +71,10 @@ \permanent\tolerant\protected\def\placeinitial[#1]% old command {\par \namedinitialparameter{#1}\c!before - \edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{}}} + \enforced\edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{}}} \permanent\tolerant\protected\def\setinitial[#1]#*[#2]% - {\edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{#2}}} + {\enforced\edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{#2}}} \permanent\tolerant\protected\def\flushinitial % when used inside a mechanism that forgets {\typo_initial_handle} @@ -110,9 +110,9 @@ \c_attr_initial\plusone \initialparameter\c!text \endgroup - \glet\typo_initial_handle\relax} + \enforced\glettonothing\typo_initial_handle} -\let\typo_initial_handle\relax +\lettonothing\typo_initial_handle % hook into everypar % \setupbodyfont[dejavu,9pt] % diff --git a/tex/context/base/mkxl/typo-fln.mkxl b/tex/context/base/mkxl/typo-fln.mkxl index 3ef688bb5..a62646fff 100644 --- a/tex/context/base/mkxl/typo-fln.mkxl +++ b/tex/context/base/mkxl/typo-fln.mkxl @@ -88,9 +88,9 @@ % \kern\zeropoint % we need a node % \hskip\zeropoint\s!plus\emwidth\relax % can be an option \endgroup - \glet\typo_firstline_handle\relax} + \glettonothing\typo_firstline_handle} -\let\typo_firstline_handle\relax +\lettonothing\typo_firstline_handle % goodie, question on list % diff --git a/tex/context/interface/mkii/keys-nl.xml b/tex/context/interface/mkii/keys-nl.xml index a0da8b763..2312b7675 100644 --- a/tex/context/interface/mkii/keys-nl.xml +++ b/tex/context/interface/mkii/keys-nl.xml @@ -1271,6 +1271,7 @@ <cd:constant name='symbolset' value='symboolset'/> <cd:constant name='symcolor' value='symkleur'/> <cd:constant name='symstyle' value='symletter'/> + <cd:constant name='synchronize' value='synchronize'/> <cd:constant name='synonym' value='synoniem'/> <cd:constant name='synonymcolor' value='synoniemkleur'/> <cd:constant name='synonymcommand' value='synoniemcommando'/> diff --git a/tex/context/modules/mkiv/x-asciimath.mkiv b/tex/context/modules/mkiv/x-asciimath.mkiv index 32eaf2af2..bd9b847d9 100644 --- a/tex/context/modules/mkiv/x-asciimath.mkiv +++ b/tex/context/modules/mkiv/x-asciimath.mkiv @@ -174,7 +174,7 @@ \def\asciimath_yes[#1]#2% {\mathematics [#1]% - {\the\everyasciimath% + {\the\everyasciimath \clf_justasciimath{\detokenize\expandafter{\normalexpanded{#2}}}}} \def\asciimath_nop#1% @@ -191,7 +191,7 @@ \def\xmlasciimath_yes[#1]#2% {\mathematics [#1]% - {\the\everyasciimath% + {\the\everyasciimath \clf_xmlasciimath{#2}}} \def\xmlasciimath_nop#1% diff --git a/tex/context/modules/mkiv/m-system-readers.mkxl b/tex/context/modules/mkxl/m-system-readers.mkxl index 0f2d3275e..0f2d3275e 100644 --- a/tex/context/modules/mkiv/m-system-readers.mkxl +++ b/tex/context/modules/mkxl/m-system-readers.mkxl diff --git a/tex/context/modules/mkiv/m-timing.mkxl b/tex/context/modules/mkxl/m-timing.mkxl index 3edfd14e2..3edfd14e2 100644 --- a/tex/context/modules/mkiv/m-timing.mkxl +++ b/tex/context/modules/mkxl/m-timing.mkxl diff --git a/tex/context/modules/mkiv/s-languages-goodies.lmt b/tex/context/modules/mkxl/s-languages-goodies.lmt index 7256fd35d..7256fd35d 100644 --- a/tex/context/modules/mkiv/s-languages-goodies.lmt +++ b/tex/context/modules/mkxl/s-languages-goodies.lmt diff --git a/tex/context/modules/mkiv/s-languages-goodies.mkxl b/tex/context/modules/mkxl/s-languages-goodies.mkxl index 3ced071be..3ced071be 100644 --- a/tex/context/modules/mkiv/s-languages-goodies.mkxl +++ b/tex/context/modules/mkxl/s-languages-goodies.mkxl diff --git a/tex/context/modules/mkiv/s-system-macros.mkxl b/tex/context/modules/mkxl/s-system-macros.mkxl index 605859000..605859000 100644 --- a/tex/context/modules/mkiv/s-system-macros.mkxl +++ b/tex/context/modules/mkxl/s-system-macros.mkxl diff --git a/tex/context/modules/mkiv/s-system-tokens.mkxl b/tex/context/modules/mkxl/s-system-tokens.mkxl index b83a4f47b..b83a4f47b 100644 --- a/tex/context/modules/mkiv/s-system-tokens.mkxl +++ b/tex/context/modules/mkxl/s-system-tokens.mkxl 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> diff --git a/tex/context/patterns/lmtx/lang-de.llg b/tex/context/patterns/mkxl/lang-de.llg index 89b8eef1f..89b8eef1f 100644 --- a/tex/context/patterns/lmtx/lang-de.llg +++ b/tex/context/patterns/mkxl/lang-de.llg diff --git a/tex/context/patterns/lmtx/lang-en.llg b/tex/context/patterns/mkxl/lang-en.llg index 5378e0aa9..5378e0aa9 100644 --- a/tex/context/patterns/lmtx/lang-en.llg +++ b/tex/context/patterns/mkxl/lang-en.llg diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index a28630bfe..96393e4c2 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2021-06-04 17:20 +-- merge date : 2021-06-07 08:05 do -- begin closure to overcome local limits and interference |