summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2019-07-31 18:26:52 +0200
committerContext Git Mirror Bot <phg@phi-gamma.net>2019-07-31 18:26:52 +0200
commit1873d112b56f49e40ece29916ede51933412bca8 (patch)
tree1ad98a73dfbf2f1a98703f31e0df9e0cdf4f260c /tex
parent47852e5715e7c0374bb6bc173c1728908549e1ed (diff)
downloadcontext-1873d112b56f49e40ece29916ede51933412bca8.tar.gz
2019-07-31 18:13:00
Diffstat (limited to 'tex')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkii/mult-it.mkii5
-rw-r--r--tex/context/base/mkiv/back-ini.mkiv35
-rw-r--r--tex/context/base/mkiv/back-ini.mkxl81
-rw-r--r--tex/context/base/mkiv/back-lua.mkxl (renamed from tex/context/base/mkiv/back-lua.mkiv)0
-rw-r--r--tex/context/base/mkiv/back-mps.mkxl (renamed from tex/context/base/mkiv/back-mps.mkiv)0
-rw-r--r--tex/context/base/mkiv/back-out.lua4
-rw-r--r--tex/context/base/mkiv/back-out.mkxl (renamed from tex/context/base/mkiv/back-out.mkiv)2
-rw-r--r--tex/context/base/mkiv/back-pdf.mkiv24
-rw-r--r--tex/context/base/mkiv/back-pdf.mkxl148
-rw-r--r--tex/context/base/mkiv/buff-ver.mkiv184
-rw-r--r--tex/context/base/mkiv/buff-ver.mkxl1005
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua2
-rw-r--r--tex/context/base/mkiv/colo-ini.mkiv151
-rw-r--r--tex/context/base/mkiv/colo-ini.mkxl1399
-rw-r--r--tex/context/base/mkiv/cont-cs.mkxl21
-rw-r--r--tex/context/base/mkiv/cont-de.mkxl21
-rw-r--r--tex/context/base/mkiv/cont-en.mkxl21
-rw-r--r--tex/context/base/mkiv/cont-fr.mkxl21
-rw-r--r--tex/context/base/mkiv/cont-gb.mkxl21
-rw-r--r--tex/context/base/mkiv/cont-it.mkxl21
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/cont-nl.mkxl21
-rw-r--r--tex/context/base/mkiv/cont-pe.mkxl22
-rw-r--r--tex/context/base/mkiv/cont-ro.mkxl21
-rw-r--r--tex/context/base/mkiv/context.mkiv11
-rw-r--r--tex/context/base/mkiv/context.mkxl625
-rw-r--r--tex/context/base/mkiv/core-lmt.mkxl (renamed from tex/context/base/mkiv/core-lmt.mkiv)11
-rw-r--r--tex/context/base/mkiv/data-tmp.lua9
-rw-r--r--tex/context/base/mkiv/driv-ini.mkiv21
-rw-r--r--tex/context/base/mkiv/driv-ini.mkxl20
-rw-r--r--tex/context/base/mkiv/driv-shp.mkxl (renamed from tex/context/base/mkiv/driv-shp.mkiv)8
-rw-r--r--tex/context/base/mkiv/file-job.lua4
-rw-r--r--tex/context/base/mkiv/file-mod.lua17
-rw-r--r--tex/context/base/mkiv/font-emp.mklx256
-rw-r--r--tex/context/base/mkiv/font-emp.mkvi29
-rw-r--r--tex/context/base/mkiv/font-fil.mklx422
-rw-r--r--tex/context/base/mkiv/font-fil.mkvi20
-rw-r--r--tex/context/base/mkiv/font-ini.mklx2563
-rw-r--r--tex/context/base/mkiv/font-ini.mkvi435
-rw-r--r--tex/context/base/mkiv/font-mat.mklx500
-rw-r--r--tex/context/base/mkiv/font-otr.lua33
-rw-r--r--tex/context/base/mkiv/font-pre.mkiv2
-rw-r--r--tex/context/base/mkiv/font-shp.lua20
-rw-r--r--tex/context/base/mkiv/font-sty.mklx449
-rw-r--r--tex/context/base/mkiv/font-sym.mklx245
-rw-r--r--tex/context/base/mkiv/font-sym.mkvi31
-rw-r--r--tex/context/base/mkiv/lang-ini.mkxl730
-rw-r--r--tex/context/base/mkiv/lang-lab.mkiv45
-rw-r--r--tex/context/base/mkiv/lang-lab.mkxl390
-rw-r--r--tex/context/base/mkiv/lpdf-eng.lua4
-rw-r--r--tex/context/base/mkiv/lpdf-lmt.lua4
-rw-r--r--tex/context/base/mkiv/lpdf-nod.lua4
-rw-r--r--tex/context/base/mkiv/luat-env.lua11
-rw-r--r--tex/context/base/mkiv/luat-fmt.lua12
-rw-r--r--tex/context/base/mkiv/luat-lib.mkiv9
-rw-r--r--tex/context/base/mkiv/luat-mac.lua4
-rw-r--r--tex/context/base/mkiv/meta-imp-dum.mkiv127
-rw-r--r--tex/context/base/mkiv/meta-mac.mkxl66
-rw-r--r--tex/context/base/mkiv/mlib-ctx.mkiv69
-rw-r--r--tex/context/base/mkiv/mlib-ctx.mkxl27
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua4
-rw-r--r--tex/context/base/mkiv/mlib-mat.lua133
-rw-r--r--tex/context/base/mkiv/mlib-run.lua7
-rw-r--r--tex/context/base/mkiv/mlib-scn.lua529
-rw-r--r--tex/context/base/mkiv/mult-aux.mkiv197
-rw-r--r--tex/context/base/mkiv/mult-aux.mkxl1154
-rw-r--r--tex/context/base/mkiv/mult-def.lua4
-rw-r--r--tex/context/base/mkiv/mult-low.lua2
-rw-r--r--tex/context/base/mkiv/mult-prm.lua9
-rw-r--r--tex/context/base/mkiv/mult-sys.mkiv1
-rw-r--r--tex/context/base/mkiv/node-nut.lua298
-rw-r--r--tex/context/base/mkiv/node-rul.lua9
-rw-r--r--tex/context/base/mkiv/pack-rul.mkiv165
-rw-r--r--tex/context/base/mkiv/pack-rul.mkxl3049
-rw-r--r--tex/context/base/mkiv/page-imp.mkiv10
-rw-r--r--tex/context/base/mkiv/scrn-wid.mkvi2
-rw-r--r--tex/context/base/mkiv/spac-ver.mkiv39
-rw-r--r--tex/context/base/mkiv/spac-ver.mkxl2597
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26920 -> 26567 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin254119 -> 268461 bytes
-rw-r--r--tex/context/base/mkiv/strc-itm.mklx1854
-rw-r--r--tex/context/base/mkiv/strc-itm.mkvi16
-rw-r--r--tex/context/base/mkiv/supp-box.mkiv431
-rw-r--r--tex/context/base/mkiv/supp-box.mkxl2930
-rw-r--r--tex/context/base/mkiv/syst-aux.mkiv2467
-rw-r--r--tex/context/base/mkiv/syst-aux.mkxl6558
-rw-r--r--tex/context/base/mkiv/syst-ini.mkiv4
-rw-r--r--tex/context/base/mkiv/syst-ini.mkxl1075
-rw-r--r--tex/context/base/mkiv/tabl-ntb.mkiv143
-rw-r--r--tex/context/base/mkiv/tabl-ntb.mkxl2138
-rw-r--r--tex/context/base/mkiv/tabl-tbl.mkxl3022
-rw-r--r--tex/context/base/mkiv/type-ini.mklx618
-rw-r--r--tex/context/base/mkiv/type-ini.mkvi20
-rw-r--r--tex/context/base/mkiv/util-sci.lua2
-rw-r--r--tex/context/base/mkiv/util-str.lua27
-rw-r--r--tex/context/base/mkiv/util-tab.lua32
-rw-r--r--tex/context/interface/mkii/keys-it.xml5
-rw-r--r--tex/context/interface/mkiv/context-en.xml2144
-rw-r--r--tex/context/interface/mkiv/i-attachment.xml3
-rw-r--r--tex/context/interface/mkiv/i-boxes.xml101
-rw-r--r--tex/context/interface/mkiv/i-capitals.xml18
-rw-r--r--tex/context/interface/mkiv/i-chart.xml2
-rw-r--r--tex/context/interface/mkiv/i-columns.xml10
-rw-r--r--tex/context/interface/mkiv/i-common-argument.xml24
-rw-r--r--tex/context/interface/mkiv/i-common-instance.xml1
-rw-r--r--tex/context/interface/mkiv/i-common-string.xml22
-rw-r--r--tex/context/interface/mkiv/i-common-value.xml127
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin967152 -> 890332 bytes
-rw-r--r--tex/context/interface/mkiv/i-context.xml2
-rw-r--r--tex/context/interface/mkiv/i-conversion.xml9
-rw-r--r--tex/context/interface/mkiv/i-direction.xml18
-rw-r--r--tex/context/interface/mkiv/i-fittingpage.xml62
-rw-r--r--tex/context/interface/mkiv/i-graphics.xml2
-rw-r--r--tex/context/interface/mkiv/i-interactionscreen.xml2
-rw-r--r--tex/context/interface/mkiv/i-itemgroup.xml730
-rw-r--r--tex/context/interface/mkiv/i-math.xml56
-rw-r--r--tex/context/interface/mkiv/i-mathfence.xml51
-rw-r--r--tex/context/interface/mkiv/i-mixedcolumns.xml10
-rw-r--r--tex/context/interface/mkiv/i-note.xml51
-rw-r--r--tex/context/interface/mkiv/i-pagegrid.xml24
-rw-r--r--tex/context/interface/mkiv/i-pagenumber.xml34
-rw-r--r--tex/context/interface/mkiv/i-paragraphs.xml1
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin27517 -> 61165 bytes
-rw-r--r--tex/context/interface/mkiv/i-register.xml605
-rw-r--r--tex/context/interface/mkiv/i-section.xml28
-rw-r--r--tex/context/interface/mkiv/i-simplecolumns.xml34
-rw-r--r--tex/context/interface/mkiv/i-symbol.xml13
-rw-r--r--tex/context/interface/mkiv/i-texts.xml331
-rw-r--r--tex/context/interface/mkiv/i-vspace.xml6
-rw-r--r--tex/context/modules/mkiv/m-scite.mkiv3
-rw-r--r--tex/context/modules/mkiv/s-fonts-system.lua2
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua42
134 files changed, 40003 insertions, 4585 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index db052cd5e..9387a9475 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{2019.07.24 11:17}
+\newcontextversion{2019.07.31 18: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 6c59c6cfa..0c0370cd4 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{2019.07.24 11:17}
+\edef\contextversion{2019.07.31 18:05}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii
index 2bbf93141..432917617 100644
--- a/tex/context/base/mkii/mult-it.mkii
+++ b/tex/context/base/mkii/mult-it.mkii
@@ -147,6 +147,7 @@
\setinterfacevariable{comment}{commento}
\setinterfacevariable{component}{componente}
\setinterfacevariable{compressseparator}{compressseparator}
+\setinterfacevariable{compressstopper}{compressstopper}
\setinterfacevariable{concept}{concetto}
\setinterfacevariable{construction}{construction}
\setinterfacevariable{content}{indice}
@@ -477,6 +478,7 @@
\setinterfacevariable{sectionnumber}{numerosezione}
\setinterfacevariable{see}{vedi}
\setinterfacevariable{selectfont}{selectfont}
+\setinterfacevariable{separator}{separator}
\setinterfacevariable{september}{settembre}
\setinterfacevariable{serif}{serif}
\setinterfacevariable{serifbold}{serifbold}
@@ -635,6 +637,7 @@
\setinterfaceconstant{aligntitle}{allineatitolo}
\setinterfaceconstant{alternative}{alternativa}
\setinterfaceconstant{anchor}{anchor}
+\setinterfaceconstant{anchoring}{anchoring}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arguments}{arguments}
@@ -732,7 +735,9 @@
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
\setinterfaceconstant{compressdistance}{compressdistance}
+\setinterfaceconstant{compressmethod}{compressmethod}
\setinterfaceconstant{compressseparator}{compressseparator}
+\setinterfaceconstant{compressstopper}{compressstopper}
\setinterfaceconstant{concerns}{concerns}
\setinterfaceconstant{connector}{connector}
\setinterfaceconstant{continue}{continua}
diff --git a/tex/context/base/mkiv/back-ini.mkiv b/tex/context/base/mkiv/back-ini.mkiv
index 007f80d1a..43fe48ee0 100644
--- a/tex/context/base/mkiv/back-ini.mkiv
+++ b/tex/context/base/mkiv/back-ini.mkiv
@@ -30,13 +30,11 @@
%D therefore dropped support for this format. Future versions might support more
%D backends again, but this has a low priority.
-\ifdefined\outputmode
- \outputmode\plusone
- \let\outputmode\relax
- \newcount\outputmode
- \outputmode\plusone
- \let\normaloutputmode\outputmode
-\fi
+\outputmode\plusone
+\let\outputmode\relax
+\newcount\outputmode
+\outputmode\plusone
+\let\normaloutputmode\outputmode
%D The exact page model depends on the backend so we just define some variables that
%D are used. A helper at the \LUA\ end will synchronize with the internal variables.
@@ -46,6 +44,9 @@
\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi
\ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi
+%D In \MKIV\ there is just one backend, \PDF, plus an additional export. We never
+%D came to seperate them, but \LMTX\ might do that.
+
\installcorenamespace{backend}
\installsetuponlycommandhandler \??backend {backend}
@@ -64,27 +65,7 @@
\fi
\to \everysetupbackend
-%D For the moment this is an experiment (defauls is pdf, but we also
-%D have lua, json and mps).
-%D
-%D \starttyping
-%D % \setupoutput[lua]
-%D % \setupoutput[json]
-%D % \setupoutput[mps]
-%D % \setupoutput[none] % for testing only
-%D % \setupoutput[empty] % for testing only
-%D
-%D \starttext
-%D \dorecurse{1000}{
-%D {\tf \red \samplefile{tufte}} \par
-%D {\bf \green \samplefile {ward}} \par
-%D {\sl \blue \samplefile{davis}} \par
-%D }
-%D \stoptext
-%D \stoptyping
-
\unexpanded\def\setupoutput[#1]%
{\clf_enabledriver{#1}}
-
\protect \endinput
diff --git a/tex/context/base/mkiv/back-ini.mkxl b/tex/context/base/mkiv/back-ini.mkxl
new file mode 100644
index 000000000..4e2fa351e
--- /dev/null
+++ b/tex/context/base/mkiv/back-ini.mkxl
@@ -0,0 +1,81 @@
+%D \module
+%D [ file=back-ini,
+%D version=2009.04.15,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=Initialization,
+%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.
+
+\writestatus{loading}{ConTeXt Backend Macros / Initialization}
+
+\registerctxluafile{back-ini}{}
+
+\unprotect
+
+%D Right from the start \CONTEXT\ had a backend system based on runtime pluggable
+%D code. As most backend issues involved specials and since postprocessors had not
+%D that much in common, we ended up with a system where we could switch backend as
+%D well as output code for multiple backends at the same time.
+%D
+%D Because \LUATEX\ has the backend built in, and since some backend issues have
+%D been moved to the frontend I decided to provide new backend code for \MKIV,
+%D starting with what was actually used.
+%D
+%D At this moment \DVI\ is no longer used for advanced document output and we
+%D therefore dropped support for this format. Future versions might support more
+%D backends again, but this has a low priority.
+
+%D The exact page model depends on the backend so we just define some variables that
+%D are used. A helper at the \LUA\ end will synchronize with the internal variables.
+%D We store these in the format.
+
+\ifdefined\everybackendshipout \else \newtoks\everybackendshipout \fi
+\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi
+\ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi
+
+\installcorenamespace{backend}
+
+\installsetuponlycommandhandler \??backend {backend}
+
+%D \starttyping
+%D \setupbackend[space=yes]
+%D \stoptyping
+
+\appendtoks
+ \clf_setrealspaces{\backendparameter\c!space}%
+\to \everysetupbackend
+
+\appendtoks
+ \ifdefined\clf_resetmapfile
+ \clf_resetmapfile
+ \fi
+\to \everysetupbackend
+
+%D For the moment this is an experiment (defauls is pdf, but we also
+%D have lua, json and mps).
+%D
+%D \starttyping
+%D % \setupoutput[lua]
+%D % \setupoutput[json]
+%D % \setupoutput[mps]
+%D % \setupoutput[none] % for testing only
+%D % \setupoutput[empty] % for testing only
+%D
+%D \starttext
+%D \dorecurse{1000}{
+%D {\tf \red \samplefile{tufte}} \par
+%D {\bf \green \samplefile {ward}} \par
+%D {\sl \blue \samplefile{davis}} \par
+%D }
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\setupoutput[#1]%
+ {\clf_enabledriver{#1}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/back-lua.mkiv b/tex/context/base/mkiv/back-lua.mkxl
index 82ba8f9f1..82ba8f9f1 100644
--- a/tex/context/base/mkiv/back-lua.mkiv
+++ b/tex/context/base/mkiv/back-lua.mkxl
diff --git a/tex/context/base/mkiv/back-mps.mkiv b/tex/context/base/mkiv/back-mps.mkxl
index 0a6640614..0a6640614 100644
--- a/tex/context/base/mkiv/back-mps.mkiv
+++ b/tex/context/base/mkiv/back-mps.mkxl
diff --git a/tex/context/base/mkiv/back-out.lua b/tex/context/base/mkiv/back-out.lua
index 8fc2a048f..9934f7847 100644
--- a/tex/context/base/mkiv/back-out.lua
+++ b/tex/context/base/mkiv/back-out.lua
@@ -6,10 +6,6 @@ if not modules then modules = { } end modules ['back-out'] = {
license = "see context related readme files"
}
-if CONTEXTLMTXMODE == 0 then
- return
-end
-
local type = type
local loadstring = loadstring
diff --git a/tex/context/base/mkiv/back-out.mkiv b/tex/context/base/mkiv/back-out.mkxl
index 492af2463..26548a0a4 100644
--- a/tex/context/base/mkiv/back-out.mkiv
+++ b/tex/context/base/mkiv/back-out.mkxl
@@ -11,8 +11,6 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\ifcase\contextlmtxmode\endinput\fi
-
\registerctxluafile{back-out}{}
\let\normalimmediate\immediate
diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv
index 80130577c..2541755a6 100644
--- a/tex/context/base/mkiv/back-pdf.mkiv
+++ b/tex/context/base/mkiv/back-pdf.mkiv
@@ -18,18 +18,8 @@
\writestatus{loading}{ConTeXt Backend Macros / PDF}
\registerctxluafile{lpdf-ini}{optimize}
-
-\ifcase\contextlmtxmode\relax
- % \doifelsefile {lpdf-nod-test.lua} {
- % \registerctxluafile{lpdf-nod-test}{}
- % } {
- \registerctxluafile{lpdf-nod}{}
- % }
- \registerctxluafile{lpdf-eng}{optimize}
-\else
- \registerctxluafile{lpdf-lmt}{optimize}
-\fi
-
+\registerctxluafile{lpdf-nod}{}
+\registerctxluafile{lpdf-eng}{optimize}
\registerctxluafile{lpdf-col}{}
\registerctxluafile{lpdf-xmp}{}
\registerctxluafile{lpdf-ano}{}
@@ -45,17 +35,7 @@
\registerctxluafile{lpdf-tag}{}
\registerctxluafile{lpdf-fmt}{}
\registerctxluafile{lpdf-pde}{}
-
-\ifcase\contextlmtxmode\else
- \registerctxluafile{lpdf-img}{optimize}
-\fi
-
\registerctxluafile{lpdf-epa}{}
-
-\ifcase\contextlmtxmode\else
- \registerctxluafile{lpdf-emb}{optimize}
-\fi
-
\registerctxluafile{lpdf-fnt}{}
\registerctxluafile{back-pdp}{}
diff --git a/tex/context/base/mkiv/back-pdf.mkxl b/tex/context/base/mkiv/back-pdf.mkxl
new file mode 100644
index 000000000..2b0c4d0b7
--- /dev/null
+++ b/tex/context/base/mkiv/back-pdf.mkxl
@@ -0,0 +1,148 @@
+%D \module
+%D [ file=back-pdf,
+%D version=2009.04.15,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=\PDF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The less there is here, the better. After a decade it is time to remove the \type
+%D {\pdf*} ones completely. For the moment I keep them commented but even that will
+%D go away.
+
+\writestatus{loading}{ConTeXt Backend Macros / PDF}
+
+\registerctxluafile{lpdf-ini}{optimize}
+\registerctxluafile{lpdf-lmt}{optimize}
+
+\registerctxluafile{lpdf-col}{}
+\registerctxluafile{lpdf-xmp}{}
+\registerctxluafile{lpdf-ano}{}
+\registerctxluafile{lpdf-res}{}
+\registerctxluafile{lpdf-mis}{}
+\registerctxluafile{lpdf-ren}{}
+\registerctxluafile{lpdf-grp}{}
+\registerctxluafile{lpdf-wid}{}
+\registerctxluafile{lpdf-fld}{}
+\registerctxluafile{lpdf-mov}{}
+\registerctxluafile{lpdf-u3d}{} % this will become a module
+\registerctxluafile{lpdf-swf}{} % this will become a module
+\registerctxluafile{lpdf-tag}{}
+\registerctxluafile{lpdf-fmt}{}
+\registerctxluafile{lpdf-pde}{}
+\registerctxluafile{lpdf-img}{optimize}
+\registerctxluafile{lpdf-epa}{}
+\registerctxluafile{lpdf-emb}{optimize}
+\registerctxluafile{lpdf-fnt}{}
+
+\registerctxluafile{back-pdp}{}
+\registerctxluafile{back-pdf}{} % some code will move to lpdf-*
+
+\loadmarkfile{back-u3d} % this will become a module
+\loadmarkfile{back-swf} % this will become a module
+
+\unprotect
+
+%D We will minimize the number of calls to \PDF\ specific primitives and delegate
+%D all management and injection of code to the backend.
+%D
+%D Because we do a lot in \LUA\ and don't want interferences, we nil most of the
+%D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable},
+%D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably
+%D have bad side effects.
+
+\unexpanded\def\pdfextension{\clf_pdfextension}
+ \def\pdffeedback {\clf_pdffeedback}
+
+%D For the moment we keep this for tikz but hopefully it will at some point use
+%D the proper ones. Consider them obsolete:
+
+\unexpanded\def\pdfliteral {\clf_pdfliteral}
+\unexpanded\def\pdfobj {\clf_pdfobj}%
+\unexpanded\def\pdflastobj {\numexpr\clf_pdflastobj\relax}
+\unexpanded\def\pdfrefobj {\clf_pdfrefobj }
+
+\unexpanded\def\pdfrestore {\clf_restore}
+\unexpanded\def\pdfsave {\clf_save}
+\unexpanded\def\pdfsetmatrix{\clf_setmatrix}
+
+ \let\pdfxform \saveboxresource
+ \let\pdflastxform \lastsavedboxresourceindex
+ \let\pdfrefxform \useboxresource
+
+%D Here are quick and dirty compression flippers, mostly used when testing something
+%D as one can best stick to the defaults that also adapt to specific standards.
+
+\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount}
+\unexpanded\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree}
+\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine }
+\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree}
+
+%D PDF/X (maybe combine the two lua calls)
+
+\setupbackend
+ [xmpfile=]
+
+\appendtoks
+ \edef\p_file{\backendparameter{xmpfile}}%
+ \ifx\p_file\empty\else
+ \clf_setxmpfile{\p_file}%
+ \fi
+\to \everysetupbackend
+
+%D This will change:
+
+\appendtoks
+ \clf_setformat
+ format {\backendparameter\c!format}%
+ level {\backendparameter\c!level}%
+ option {\backendparameter\c!option}%
+ profile {\backendparameter\c!profile}%
+ intent {\backendparameter\c!intent}%
+ file {\backendparameter\c!file}%
+ \relax
+\to \everysetupbackend
+
+%D These are the only official methods to add stuff to the resources. If more is
+%D needed for third party low level code, it can be added.
+
+\unexpanded\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}}
+\unexpanded\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}}
+\unexpanded\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}}
+
+\unexpanded\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}}
+\unexpanded\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}}
+\unexpanded\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}}
+
+\unexpanded\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}}
+\unexpanded\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}}
+\unexpanded\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}}
+\unexpanded\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}}
+
+ \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources}
+ \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax}
+
+%D This is a temporary hack mthat will be removed, improved or somehow can become
+%D default.
+
+\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]}
+
+%D Just in case one needs this \unknown:
+%D
+%D \starttyping
+%D text \pdfbackendactualtext{Meier}{Müller} text
+%D \stoptyping
+
+\unexpanded\def\pdfbackendactualtext#1#2% not interfaced
+ {\clf_startactualtext{#2}%
+ #1%
+ \clf_stopactualtext}
+
+\let\pdfactualtext\pdfbackendactualtext
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv
index 91778bc4a..75ee992e4 100644
--- a/tex/context/base/mkiv/buff-ver.mkiv
+++ b/tex/context/base/mkiv/buff-ver.mkiv
@@ -140,8 +140,7 @@
%D \macros
%D {definetype,setuptype}
%D
-%D Specific inline verbatim commands can be defined with the
-%D following command.
+%D Specific inline verbatim commands can be defined with the following command.
\installcorenamespace{type}
@@ -158,9 +157,8 @@
%D \macros
%D {definetyping,setuptyping}
%D
-%D For most users the standard \type{\start}||\type{\stop}||pair
-%D will suffice, but for documentation purposes the next
-%D definition command can be of use:
+%D For most users the standard \type {\start}||\type {\stop}||pair will suffice, but
+%D for documentation purposes the next definition command can be of use:
%D
%D \starttyping
%D \definetyping[extratyping][margin=3em]
@@ -198,31 +196,27 @@
\let\doifvisualizerelse\doifelsevisualizer
-%D Verbatim command are very sensitive to argument processing,
-%D which is a direct result of the \CATCODES\ being fixed at
-%D reading time.
+%D Verbatim command are very sensitive to argument processing, which is a direct
+%D result of the \CATCODES\ being fixed at reading time.
%D
-%D Typesetting inline verbatim can be accomplished by
-%D \type{\type}, which in this sentence was typeset by saying
-%D just \type{\type{\type}}, which in turn was typeset by
-%D \unknown. Using the normal grouping characters \type{{}} is
-%D the most natural way of using this command.
+%D Typesetting inline verbatim can be accomplished by \type {\type}, which in this
+%D sentence was typeset by saying just \type {\type {\type}}, which in turn was
+%D typeset by \unknown. Using the normal grouping characters \type {{}} is the most
+%D natural way of using this command.
%D
-%D A second, more or less redundant, alternative is delimiting
-%D the argument with an own character. This method was
-%D implemented in the context of a publication in the \MAPS,
-%D where this way of delimiting is recognized by \LATEX\ users.
+%D A second, more or less redundant, alternative is delimiting the argument with an
+%D own character. This method was implemented in the context of a publication in the
+%D \MAPS, where this way of delimiting is recognized by \LATEX\ users.
+%D
+%D The third, more original alternative, is the one using \type {<<} and \type {>>}
+%D as delimiters. This alternative can be used in situations where slanted
+%D typeseting is needed.
%D
-%D The third, more original alternative, is the one using
-%D \type{<<} and \type{>>} as delimiters. This alternative can
-%D be used in situations where slanted typeseting is needed.
-
%D \macros
%D {type}
%D
-%D We define \type{\type} as a protected command. This command
-%D has several invocations: grouped, wirt boundary characters,
-%D and with font switches.
+%D We define \type {\type} as a protected command. This command has several
+%D invocations: grouped, wirt boundary characters, and with font switches.
%D
%D \starttyping
%D normal: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
@@ -234,17 +228,14 @@
%D none: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
%D \stoptyping
%D
-%D When writing the manual to \CONTEXT\ and documenting this
-%D source we needed to typeset \type{<<} and \type{>>}. Because
-%D we wanted to do this in the natural way, we've adapted the
-%D original definition a bit. This implementation went through
-%D several live cycles. The final implementation looks a bit
-%D further and treats the lone \type{<<} and \type{>>} a bit
-%D different. The \type {\null} prevents ligatures, which
-%D unfortunately turn up in Lucida fonts.
+%D When writing the manual to \CONTEXT\ and documenting this source we needed to
+%D typeset \type {<<} and \type {>>}. Because we wanted to do this in the natural
+%D way, we've adapted the original definition a bit. This implementation went
+%D through several live cycles. The final implementation looks a bit further and
+%D treats the lone \type {<<} and \type {>>} a bit different. The \type {\null}
+%D prevents ligatures, which unfortunately turn up in Lucida fonts.
%D
-%D The following lines show what happens when we set
-%D \type {option=commands}.
+%D The following lines show what happens when we set \type {option=commands}.
%D
%D \startbuffer
%D \starttyping
@@ -261,9 +252,8 @@
%D
%D \typebuffer
-% Beware, the command is supposed to do something like \framed and not
-% manipulate content i.e. it gets no argument but something b/egrouped
-% instead:
+% Beware, the command is supposed to do something like \framed and not manipulate
+% content i.e. it gets no argument but something b/egrouped instead:
\def\buff_verbatim_left_of_type
{\typeparameter\c!left
@@ -294,38 +284,21 @@
\let\specialobeyedspace\specialstretchedspace
\doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop}
-\startmkivmode
-
- \def\buff_verbatim_type_nop
- {\buff_verbatim_left_of_type
- \futurelet\next\buff_verbatim_type_one}
-
- \def\buff_verbatim_type_one
- {\ifx\next\bgroup
- \expandafter\buff_verbatim_type_a
- \else
- \expandafter\buff_verbatim_type_two
- \fi}
-
- \def\buff_verbatim_type_two
- {\catcode`<=\othercatcode % old precaution
- \catcode`>=\othercatcode % old precaution
- \futurelet\next\buff_verbatim_type_three}
+\def\buff_verbatim_type_nop
+ {\buff_verbatim_left_of_type
+ \futurelet\next\buff_verbatim_type_one}
-\stopmkivmode
-
-\startlmtxmode
-
- \def\buff_verbatim_type_nop
- {\buff_verbatim_left_of_type
- \futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one}
-
- \def\buff_verbatim_type_one
- {\catcode`<=\othercatcode % old precaution
- \catcode`>=\othercatcode % old precaution
- \futureexpandis<\buff_verbatim_type_b\buff_verbatim_type_c}
+\def\buff_verbatim_type_one
+ {\ifx\next\bgroup
+ \expandafter\buff_verbatim_type_a
+ \else
+ \expandafter\buff_verbatim_type_two
+ \fi}
-\stoplmtxmode
+\def\buff_verbatim_type_two
+ {\catcode`<=\othercatcode % old precaution
+ \catcode`>=\othercatcode % old precaution
+ \futurelet\next\buff_verbatim_type_three}
\def\buff_verbatim_type_three
{\if\next<%
@@ -396,12 +369,11 @@
%D \macros
%D {obeyhyphens,obeybreakpoints}
%D
-%D Although it's not clear from the macros, one character
-%D trait of this macros, which are build on top of the support
-%D module, is that they don't hyphenate. We therefore offer
-%D the alternative \type{\typ}. The current implementation
-%D works all right, but a decent hyphenation support of
-%D \type{\tt} text will be implemented soon.
+%D Although it's not clear from the macros, one character trait of this macros,
+%D which are build on top of the support module, is that they don't hyphenate. We
+%D therefore offer the alternative \type{\typ}. The current implementation works all
+%D right, but a decent hyphenation support of \type{\tt} text will be implemented
+%D soon.
\unexpanded\def\specialfixedspace {\kern\interwordspace\relax}
\unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
@@ -435,13 +407,11 @@
%D \macros
%D {tex,arg,mat,dis,astype}
%D
-%D Sometimes, for instance when we pass verbatim text as an
-%D argument, the fixed \CATCODES\ interfere with our wishes. An
-%D experimental implementation of character by character
-%D processing of verbatim text did overcome this limitation,
-%D but we've decided not to use that slow and sometimes
-%D troublesome solution. Instead we stick to some 'old'
-%D \CONTEXT\ macros for typesetting typical \TEX\ characters.
+%D Sometimes, for instance when we pass verbatim text as an argument, the fixed
+%D \CATCODES\ interfere with our wishes. An experimental implementation of character
+%D by character processing of verbatim text did overcome this limitation, but we've
+%D decided not to use that slow and sometimes troublesome solution. Instead we stick
+%D to some 'old' \CONTEXT\ macros for typesetting typical \TEX\ characters.
\def\lesscharacter {<} % obsolete
\def\morecharacter {>} % obsolete
@@ -490,32 +460,18 @@
\let\beginofverbatimlines\relax % hooks
\let\endofverbatimlines \relax % hooks
-\startmkivmode
-
- \unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead
- {\begingroup
- \edef\currenttyping{#1}%
- \obeylines
- \futurelet\nexttoken\buff_verbatim_typing_start_indeed}
-
- \def\buff_verbatim_typing_start_indeed
- {\ifx\nexttoken[%
- \expandafter\buff_verbatim_typing_start_yes
- \else
- \expandafter\buff_verbatim_typing_start_nop
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead
- {\begingroup
- \edef\currenttyping{#1}%
- \obeylines
- \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop}
+\unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead
+ {\begingroup
+ \edef\currenttyping{#1}%
+ \obeylines
+ \futurelet\nexttoken\buff_verbatim_typing_start_indeed}
-\stoplmtxmode
+\def\buff_verbatim_typing_start_indeed
+ {\ifx\nexttoken[%
+ \expandafter\buff_verbatim_typing_start_yes
+ \else
+ \expandafter\buff_verbatim_typing_start_nop
+ \fi}
\unexpanded\def\buff_verbatim_setup_keep_together
{\edef\p_keeptogether{\typingparameter\c!keeptogether}%
@@ -593,8 +549,8 @@
\endgroup
\dorechecknextindentation}
-%D Line numbering for files is combined with filtering, while
-%D display verbatim has the ability to continue.
+%D Line numbering for files is combined with filtering, while display verbatim has
+%D the ability to continue.
%D
%D \starttyping
%D \typefile[numbering=file,start=10,stop=12]{test.tex}
@@ -640,10 +596,9 @@
%D \macros
%D {typefile}
%D
-%D Typesetting files verbatim (for the moment) only supports
-%D colorization of \TEX\ sources as valid option. The other
-%D setup values are inherited from display verbatim.
-%D The implementation of \type{\typefile} is straightforward:
+%D Typesetting files verbatim (for the moment) only supports colorization of \TEX\
+%D sources as valid option. The other setup values are inherited from display
+%D verbatim. The implementation of \type {\typefile} is straightforward:
% [category] [settings] {name} % for historic reasons, all filenames are {}
@@ -784,10 +739,9 @@
\unexpanded\def\verbatim#1{\detokenize{#1}}
-%D The setups for display verbatim and file verbatim are
-%D shared. One can adapt the extra defined typing environments,
-%D but they also default to the values below. Watch the
-%D alternative escape character.
+%D The setups for display verbatim and file verbatim are shared. One can adapt the
+%D extra defined typing environments, but they also default to the values below.
+%D Watch the alternative escape character.
% \tttf gives problems with {\tx \type...}
% \tt\tf does not adapt to e.g. \bf
diff --git a/tex/context/base/mkiv/buff-ver.mkxl b/tex/context/base/mkiv/buff-ver.mkxl
new file mode 100644
index 000000000..dec4dfb4a
--- /dev/null
+++ b/tex/context/base/mkiv/buff-ver.mkxl
@@ -0,0 +1,1005 @@
+%D \module
+%D [ file=buff-ver, % was core-ver
+%D version=2000.05.09,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Verbatim,
+%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.
+
+% check after-first and before-last breaks
+
+\writestatus{loading}{ConTeXt Buffer Macros / Verbatim}
+
+\registerctxluafile{buff-ver}{}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+\definesystemattribute[verbatimline][public]
+
+\appendtoksonce
+ \attribute\verbatimlineattribute\attributeunsetvalue
+\to \everyforgetall
+
+%D Initializations.
+
+\installcorenamespace{typinglines}
+\installcorenamespace{typingspace}
+\installcorenamespace{typingblank} % needs checking ... used?
+
+\newtoks\everyinitializeverbatim
+
+\appendtoks
+ \the\everyresettypesetting
+ \resetfontfeature
+ \resetcharacterspacing
+\to \everyinitializeverbatim
+
+\unexpanded\def\setverbatimspaceskip % to be checked: must happen after font switch
+ {\spaceskip\fontcharwd\font`x\relax
+ \xspaceskip\spaceskip}
+
+\setvalue{\??typinglines\v!no }{\buff_verbatim_ignore_hyphens}
+\setvalue{\??typinglines\v!normal }{\buff_verbatim_ignore_hyphens}
+\setvalue{\??typinglines\v!yes }{\buff_verbatim_obey_breakpoints}
+\setvalue{\??typinglines\v!hyphenated}{\buff_verbatim_obey_hyphens}
+
+\setvalue{\??typingspace\v!on }{\let\obeyedspace\specialcontrolspace}
+\setvalue{\??typingspace\v!stretch }{\let\obeyedspace\specialstretchedspace}
+\setvalue{\??typingspace\v!normal }{}
+\setvalue{\??typingspace\v!fixed }{\let\obeyedspace\specialfixedspace}
+
+\setvalue{\??typingblank\v!standard }{\s_spac_whitespace_parskip}
+\setvalue{\??typingblank\v!small }{\smallskipamount}
+\setvalue{\??typingblank\v!medium }{\medskipamount}
+\setvalue{\??typingblank\v!big }{\bigskipamount}
+\setvalue{\??typingblank\v!halfline }{.5\baselineskip}
+\setvalue{\??typingblank\v!line }{\baselineskip}
+\setvalue{\??typingblank\v!none }{\zeropoint}
+
+\unexpanded\def\buff_verbatim_obey_hyphens
+ {}
+
+\unexpanded\def\buff_verbatim_obey_breakpoints
+ {\language\minusone % tricky as this affects the pagebuilder
+ \veryraggedright}
+
+\unexpanded\def\buff_verbatim_ignore_hyphens
+ {\language\minusone} % tricky as this affects the pagebuilder
+
+\def\buff_verbatim_initialize_type_one
+ {\let\obeylines\ignorelines
+ \edef\p_buff_option{\typeparameter\c!option}%
+ \ifx\p_buff_option\v!none
+ \usetypestyleandcolor\c!style\c!color
+ \orelse\ifx\p_buff_option\empty
+ \usetypestyleandcolor\c!style\c!color
+ \else
+ \usetypestyleparameter\c!style % no color
+ \fi
+ \setcatcodetable\vrbcatcodes}
+
+\def\buff_verbatim_initialize_type_two
+ {\spaceskip.5\emwidth\relax
+ \let\obeyedspace\specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \edef\p_buff_lines{\typeparameter\c!lines}%
+ \begincsname\??typinglines\p_buff_lines\endcsname
+ \edef\p_buff_space{\typeparameter\c!space}%
+ \begincsname\??typingspace\p_buff_space\endcsname
+ \relax\the\everyinitializeverbatim\relax}
+
+\unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
+ {\buff_verbatim_initialize_type_one
+ \buff_verbatim_initialize_type_two}
+
+\let\buff_verbatim_set_line_margin\relax
+
+\def\buff_verbatim_set_line_margin_indeed
+ {\hskip\doifelseoddpage{\typingparameter\c!oddmargin}{\typingparameter\c!evenmargin}\relax}
+
+\def\buff_verbatim_initialize_typing_one
+ {\usebodyfontparameter\typingparameter
+ \scratchskip\typingparameter\c!oddmargin\relax
+ \ifzeropt\scratchskip \else
+ \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
+ \fi
+ \scratchskip\typingparameter\c!evenmargin\relax
+ \ifzeropt\scratchskip \else
+ \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
+ \fi
+ \ifx\buff_verbatim_set_line_margin\relax
+ \doadaptleftskip{\typingparameter\c!margin}%
+ \fi
+ \edef\p_buff_option{\typingparameter\c!option}%
+ \ifx\p_buff_option\v!none
+ \usetypingstyleandcolor\c!style\c!color
+ \orelse\ifx\p_buff_option\empty
+ \usetypingstyleandcolor\c!style\c!color
+ \else
+ \usetypingstyleparameter\c!style % no color !
+ \fi
+ \usealignparameter\typingparameter}
+
+\def\buff_verbatim_initialize_typing_two
+ {\spaceskip.5\emwidth\relax
+ \let\obeyedspace\specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \edef\p_buff_lines{\typingparameter\c!lines}%
+ \begincsname\??typinglines\p_buff_lines\endcsname
+ \edef\p_buff_space{\typingparameter\c!space}%
+ \begincsname\??typingspace\p_buff_space\endcsname
+ \relax\the\everyinitializeverbatim\relax}
+
+%D \macros
+%D {definetype,setuptype}
+%D
+%D Specific inline verbatim commands can be defined with the following command.
+
+\installcorenamespace{type}
+
+\installcommandhandler \??type {type} \??type
+
+\appendtoks
+ \setuevalue{\currenttype}{\buff_verbatim_type{\currenttype}}%
+\to \everydefinetype
+
+\appendtoks
+ \buff_verbatim_initialize_visualizer{\typeparameter\c!option}%
+\to \everysetuptype
+
+%D \macros
+%D {definetyping,setuptyping}
+%D
+%D For most users the standard \type {\start}||\type {\stop}||pair will suffice, but
+%D for documentation purposes the next definition command can be of use:
+%D
+%D \starttyping
+%D \definetyping[extratyping][margin=3em]
+%D
+%D \startextratyping
+%D these extra ones are indented by 1 em
+%D \stopextratyping
+%D \stoptyping
+%D
+%D The definitions default to the standard typing values.
+
+\installcorenamespace{typing}
+
+\installcommandhandler \??typing {typing} \??typing
+
+\appendtoks
+ \setuevalue{\e!start\currenttyping}{\buff_verbatim_typing_start{\currenttyping}}%
+ \setuevalue{\e!stop \currenttyping}{\buff_verbatim_typing_stop {\currenttyping}}%
+ \ifx\currenttypingparent\empty
+ \normalexpanded{\definelinenumbering[\currenttyping]}%
+ \else
+ \normalexpanded{\definelinenumbering[\currenttyping][\currenttypingparent]}%
+ \fi
+\to \everydefinetyping
+
+\appendtoks
+ \buff_verbatim_initialize_visualizer{\typingparameter\c!option}% we can check at the tex end
+\to \everysetuptyping
+
+\def\buff_verbatim_initialize_visualizer#1%
+ {\ifproductionrun\clf_loadvisualizer{#1}\fi}
+
+\unexpanded\def\doifelsevisualizer#1%
+ {\clf_doifelsevisualizer{#1}}
+
+\let\doifvisualizerelse\doifelsevisualizer
+
+%D Verbatim command are very sensitive to argument processing, which is a direct
+%D result of the \CATCODES\ being fixed at reading time.
+%D
+%D Typesetting inline verbatim can be accomplished by \type {\type}, which in this
+%D sentence was typeset by saying just \type {\type {\type}}, which in turn was
+%D typeset by \unknown. Using the normal grouping characters \type {{}} is the most
+%D natural way of using this command.
+%D
+%D A second, more or less redundant, alternative is delimiting the argument with an
+%D own character. This method was implemented in the context of a publication in the
+%D \MAPS, where this way of delimiting is recognized by \LATEX\ users.
+%D
+%D The third, more original alternative, is the one using \type {<<} and \type {>>}
+%D as delimiters. This alternative can be used in situations where slanted
+%D typeseting is needed.
+%D
+%D \macros
+%D {type}
+%D
+%D We define \type {\type} as a protected command. This command has several
+%D invocations: grouped, wirt boundary characters, and with font switches.
+%D
+%D \starttyping
+%D normal: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
+%D normal: \par \type{xx<..xx..<xx <slanted> >..>xx} \par \type{<....>} \par \type{<..<xx>..>}
+%D \setuptype[option=slanted]
+%D slanted: \par \type{xx<<..sl..<<xx <<sl>> xx>>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<<sl>>..>> \par
+%D slanted: \par \type{xx<<..sl..<xx <sl> xx>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<sl>..>> \par
+%D \setuptype[option=none]
+%D none: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
+%D \stoptyping
+%D
+%D When writing the manual to \CONTEXT\ and documenting this source we needed to
+%D typeset \type {<<} and \type {>>}. Because we wanted to do this in the natural
+%D way, we've adapted the original definition a bit. This implementation went
+%D through several live cycles. The final implementation looks a bit further and
+%D treats the lone \type {<<} and \type {>>} a bit different. The \type {\null}
+%D prevents ligatures, which unfortunately turn up in Lucida fonts.
+%D
+%D The following lines show what happens when we set \type {option=commands}.
+%D
+%D \startbuffer
+%D \starttyping
+%D test//test test/BTEX \footnote{test test test}/ETEX test
+%D test//test test/BTEX \footnote{test test test}/ETEX test
+%D test test test/BTEX \bf(nota bene)/ETEX test
+%D test test test /BTEX \bf(nota bene)/ETEX test
+%D \stoptyping
+%D \stopbuffer
+%D
+%D % \bgroup\setuptyping[option=commands]\getbuffer\egroup
+%D
+%D this was keyed in as:
+%D
+%D \typebuffer
+
+% Beware, the command is supposed to do something like \framed and not manipulate
+% content i.e. it gets no argument but something b/egrouped instead:
+
+\def\buff_verbatim_left_of_type
+ {\typeparameter\c!left
+ \typeparameter\c!command\bgroup}
+
+\def\buff_verbatim_right_of_type
+ {\egroup
+ \typeparameter\c!right}
+
+\unexpanded\def\type{\buff_verbatim_type\empty}
+\unexpanded\def\typ {\buff_verbatim_typ \empty}
+
+\unexpanded\def\buff_verbatim_type#1%
+ {\dontleavehmode
+ \bgroup
+ \edef\currenttype{#1}%
+ \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop}
+
+\def\buff_verbatim_type_yes[#1]%
+ {\setupcurrenttype[#1]%
+ \buff_verbatim_type_nop}
+
+\def\buff_verbatim_typ#1%
+ {\dontleavehmode
+ \bgroup
+ \edef\currenttype{#1}%
+ \lettypeparameter\c!lines\v!hyphenated
+ \let\specialobeyedspace\specialstretchedspace
+ \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop}
+
+\def\buff_verbatim_type_nop
+ {\buff_verbatim_left_of_type
+ \futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one}
+
+\def\buff_verbatim_type_one
+ {\catcode`<=\othercatcode % old precaution
+ \catcode`>=\othercatcode % old precaution
+ \futureexpandis<\buff_verbatim_type_b\buff_verbatim_type_c}
+
+\def\buff_verbatim_type_three
+ {\if\next<%
+ \expandafter\buff_verbatim_type_b
+ \else
+ \expandafter\buff_verbatim_type_c
+ \fi}
+
+\def\buff_verbatim_type_a
+ {\buff_verbatim_initialize_type_one
+ \setcatcodetable\tpacatcodes
+ \buff_verbatim_type_normal}
+
+\def\buff_verbatim_type_b#1%
+ {\buff_verbatim_initialize_type_one
+ \setcatcodetable\tpbcatcodes
+ \buff_verbatim_type_nested}
+
+\def\buff_verbatim_type_c#1%
+ {\buff_verbatim_initialize_type_one
+ \setcatcodetable\vrbcatcodes
+ \def\next##1#1{\buff_verbatim_type_normal{##1}}%
+ \next}
+
+\def\buff_verbatim_type_normal#1%
+ {\buff_verbatim_initialize_type_two
+ \dostarttaggedchained\t!verbatim\currenttype\??type
+ \clf_type
+ data {\detokenize{#1}}%
+ tab {\typeparameter\c!tab}%
+ method {\p_buff_option}%
+ compact {\typeparameter\c!compact}% % none | all | last (all needed in tabulate etc for manuals)
+ escape {\typeparameter\c!escape}% % new but rather useless imo (escaping in general is not used much)
+ % nature {inline}% is default
+ \relax
+ \dostoptagged
+ \buff_verbatim_right_of_type
+ \egroup}
+
+\def\buff_verbatim_type_nested#1%
+ {\buff_verbatim_initialize_type_two
+ \dostarttaggedchained\t!verbatim\currenttype\??type
+ \clf_type
+ data {\detokenize{#1}}%
+ tab {\typeparameter\c!tab}%
+ method {\p_buff_option}% % extra visualizer (maybe: nested,\typeparameter\c!option)
+ escape {\typeparameter\c!escape}% % new but rather useless imo (escaping in general is not used much)
+ % nature {inline}% is default
+ method {nested}%
+ \relax
+ \dostoptagged
+ \buff_verbatim_right_of_type
+ \egroup
+ \gobbleoneargument} % grab last >
+
+%D The \type {compact} option can come in handy in the case of inline argument passing
+%D
+%D \starttyping
+%D \definetype[TeXcodeA][option=TEX]
+%D \definetype[TeXcodeB][option=TEX,compact=all]
+%D \definetype[TeXcodeC][option=TEX,compact=absolute]
+%D
+%D \def\argA#1{\TeXcodeA{{#1}}}
+%D \def\argB#1{\TeXcodeB{{#1}}}
+%D \def\argC#1{\TeXcodeC{{#1}}}
+%D \stoptyping
+
+%D \macros
+%D {obeyhyphens,obeybreakpoints}
+%D
+%D Although it's not clear from the macros, one character trait of this macros,
+%D which are build on top of the support module, is that they don't hyphenate. We
+%D therefore offer the alternative \type{\typ}. The current implementation works all
+%D right, but a decent hyphenation support of \type{\tt} text will be implemented
+%D soon.
+
+\unexpanded\def\specialfixedspace {\kern\interwordspace\relax}
+\unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
+\unexpanded\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero
+\unexpanded\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback
+
+\unexpanded\def\explicitfixedspace {\asciispacechar}
+\unexpanded\def\explicitobeyedspace {\asciispacechar\allowbreak}
+\unexpanded\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}%
+\unexpanded\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace
+
+\appendtoks
+ \unexpanded\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}%
+\to \everyenableelements
+
+\unexpanded\def\obeyhyphens
+ {\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace
+ \let\controlspace\specialcontrolspace
+ \spaceskip.25\emwidth\relax} % hm a bit of stretch !
+
+\unexpanded\def\obeybreakpoints
+ {\ignorehyphens
+ \veryraggedright}
+
+\unexpanded\def\ignorehyphens
+ {\language\minusone % extra bonus, the \null should do the job too
+ \let\obeyedspace \specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \spaceskip.5\emwidth\relax}
+
+%D \macros
+%D {tex,arg,mat,dis,astype}
+%D
+%D Sometimes, for instance when we pass verbatim text as an argument, the fixed
+%D \CATCODES\ interfere with our wishes. An experimental implementation of character
+%D by character processing of verbatim text did overcome this limitation, but we've
+%D decided not to use that slow and sometimes troublesome solution. Instead we stick
+%D to some 'old' \CONTEXT\ macros for typesetting typical \TEX\ characters.
+
+\def\lesscharacter {<} % obsolete
+\def\morecharacter {>} % obsolete
+
+\let\texescape \textbackslash
+\let\leftargument \textbraceleft
+\let\rightargument \textbraceright
+\let\inlinemathmarker \textdollar
+\def\displaymathmarker{\textdollar\textdollar}
+
+\def\buff_verbatim_special_type#1#2#% # gobbles spaces
+ {\dontleavehmode\bgroup
+ \buff_verbatim_initialize_type_one
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+ #1%
+ \bgroup % else wrong font for #2
+ \aftergroup#2%
+ \aftergroup\egroup
+ \let\nexttoken}
+
+\unexpanded\def\tex{\buff_verbatim_special_type\texescape \relax}
+\unexpanded\def\arg{\buff_verbatim_special_type\leftargument \rightargument}
+\unexpanded\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker}
+\unexpanded\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker}
+
+\let\normaltexttex\tex
+\let\normaltextarg\arg
+\let\normaltextmat\mat
+\let\normaltextdis\dis
+
+\unexpanded\def\astype
+ {\dontleavehmode
+ \bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken}
+
+\unexpanded\def\asciistr#1% used in some old styles
+ {\dontleavehmode\begingroup
+ \dostarttagged\t!verbatim\empty
+ \usetypestyleandcolor\c!style\c!color\detokenize{#1}%
+ \dostoptagged
+ \endgroup}
+
+%D The basic display verbatim commands are defined in an indirect way. As we
+%D will see, they are a specific case of a more general mechanism.
+
+\let\beginofverbatimlines\relax % hooks
+\let\endofverbatimlines \relax % hooks
+
+\unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead
+ {\begingroup
+ \edef\currenttyping{#1}%
+ \obeylines
+ \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop}
+
+\unexpanded\def\buff_verbatim_setup_keep_together
+ {\edef\p_keeptogether{\typingparameter\c!keeptogether}%
+ \ifx\p_keeptogether\v!yes
+ \settrue \c_buff_optimize_linebreaks
+ \else
+ \setfalse\c_buff_optimize_linebreaks
+ \fi}
+
+\def\buff_verbatim_typing_start_nop
+ {\typingparameter\c!before
+ \startpacked[\v!blank]%
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_setup_keep_together
+ \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}}
+
+\def\buff_verbatim_typing_start_yes[#1]%
+ {\typingparameter\c!before
+ \startpacked[\v!blank]%
+ \ifcondition\validassignment{#1}%
+ \setupcurrenttyping[#1]%
+ \else
+ \doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}%
+ \fi
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_setup_keep_together
+ \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}}
+
+\unexpanded\def\buff_verbatim_type_block#1#2%
+ {\edef\p_strip{\typingparameter\c!strip}%
+ \normalexpanded{\buff_pickup
+ {_typing_}%
+ {#1}%
+ {#2}%
+ {}%
+ {\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}%
+ \ifx\p_strip\v!no\zerocount\else\plusone\fi}}
+
+\unexpanded\def\buff_verbatim_type_block_verbatim_indeed#1#2%
+ {\buff_verbatim_initialize_typing_two
+ \dostarttaggedchained\t!verbatimblock\currenttyping\??typing
+ \beginofverbatimlines
+ \dostarttagged\t!verbatimlines\empty
+ \clf_typebuffer
+ name {_typing_}%
+ strip {\typingparameter\c!strip}%
+ range {\typingparameter\c!range}%
+ tab {\typingparameter\c!tab}%
+ method {\p_buff_option}%
+ escape {\typingparameter\c!escape}%
+ nature {display}%
+ \relax
+ \dostoptagged
+ \endofverbatimlines
+ \dostoptagged
+ \begincsname#2\endcsname}
+
+\unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping
+ {\stoppacked
+ \typingparameter\c!after
+ \useindentnextparameter\typingparameter
+ \endgroup
+ \dorechecknextindentation}
+
+%D Line numbering for files is combined with filtering, while display verbatim has
+%D the ability to continue.
+%D
+%D \starttyping
+%D \typefile[numbering=file,start=10,stop=12]{test.tex}
+%D
+%D \definetyping[code][numbering=line]
+%D
+%D \starttext
+%D \startcode
+%D ...
+%D ...
+%D \stopcode
+%D
+%D \startcode[start=continue]
+%D ...
+%D ...
+%D \stopcode
+%D
+%D \startcode[start=10]
+%D ...
+%D \stopcode
+%D \stoptyping
+
+%D Ranges:
+%D
+%D \starttyping
+%D % label:start:one
+%D
+%D \def\MyMacro
+%D {just an example}
+%D
+%D % label:stop:one
+%D
+%D \starttext
+%D
+%D % \typefile[file][range={3,6}] {whatever.tex}
+%D % \typefile[file][range={3,+2}]{whatever.tex}
+%D
+%D \typefile[file][range={label:start:one,label:stop:one}]{whatever.tex}
+%D
+%D \stoptext
+%D \stoptyping
+
+%D \macros
+%D {typefile}
+%D
+%D Typesetting files verbatim (for the moment) only supports colorization of \TEX\
+%D sources as valid option. The other setup values are inherited from display
+%D verbatim. The implementation of \type {\typefile} is straightforward:
+
+% [category] [settings] {name} % for historic reasons, all filenames are {}
+
+\unexpanded\def\typefile
+ {\dodoubleempty\buff_verbatim_type_file}
+
+\appendtoks
+ \setuevalue{\e!type\currenttyping\v!file}{\typefile[\currenttyping]}%
+\to \everydefinetyping
+
+\def\buff_verbatim_type_file[#1][#2]#3%
+ {\begingroup
+ \ifsecondargument
+ \setuptyping[#1][#2]%
+ \buff_verbatim_type_file_checked{#1}{#3}%
+ \orelse\iffirstargument
+ \ifcondition\validassignment{#1}%
+ \setuptyping[\v!file][#1]%
+ \buff_verbatim_type_file_checked\v!file{#3}%
+ \else
+ \buff_verbatim_type_file_checked{#1}{#3}%
+ \fi
+ \else
+ \buff_verbatim_type_file_checked\v!file{#3}%
+ \fi
+ \useindentnextparameter\typingparameter % needs checking
+ \endgroup
+ \dorechecknextindentation} % needs checking
+
+\def\buff_verbatim_type_file_checked#1#2%
+ {\doifelsetypingfile{#2}
+ {\buff_verbatim_type_file_indeed{#1}\askedtypingfile}
+ {\showmessage\m!verbatims1{#2}}}
+
+\unexpanded\def\doifelsetypingfile#1%
+ {\edef\askedtypingfile{\locfilename{#1}}%
+ \ifx\askedtypingfile\empty
+ \edef\askedtypingfile{\locfilename{#1.tex}}% downward compatible
+ \fi
+ \ifx\askedtypingfile\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doiftypingfileelse\doifelsetypingfile
+
+\def\buff_verbatim_type_file_indeed#1#2% category name
+ {\edef\currenttyping{#1}%
+ \typingparameter\c!before
+ \startpacked[\v!blank]
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_initialize_typing_two
+ \dostarttaggedchained\t!verbatimblock\currenttyping\??typing
+ \beginofverbatimlines
+ \dostarttagged\t!verbatimlines\empty
+ \clf_typefile
+ name {#2}%
+ strip {\typingparameter\c!strip}%
+ range {\typingparameter\c!range}%
+ regime {\currentregime}%
+ tab {\typingparameter\c!tab}%
+ method {\p_buff_option}%
+ nature {display}%
+ \relax
+ \dostoptagged
+ \endofverbatimlines
+ \dostoptagged
+ \stoppacked
+ \typingparameter\c!after}
+
+%D Line numbering:
+
+\newconditional\verbatimnumberinglines
+
+\def\beginofverbatimlinenumbering
+ {\startlinenumbering
+ [\currenttyping]%
+ [\c!continue=\typingparameter\c!continue,
+ \c!method=\v!type,
+ \c!start=\typingparameter\c!start,
+ \c!stop=\typingparameter\c!stop, % ?
+ \c!step=\typingparameter\c!step]}
+
+\def\endofverbatimlinenumbering
+ {\stoplinenumbering}
+
+\def\buff_verbatim_setup_line_numbering
+ {\ifdefined\startlinenumbering
+ \edef\currenttypingnumbering{\typingparameter\c!numbering}%
+ \ifx\currenttypingnumbering\v!file
+ \setuplinenumbering[\currenttyping][\c!method=\v!file]%
+ \settrue\verbatimnumberinglines
+ \orelse\ifx\currenttypingnumbering\v!line
+ \settrue\verbatimnumberinglines
+ \else
+ \setfalse\verbatimnumberinglines
+ \fi
+ \ifconditional\verbatimnumberinglines
+ \let\beginofverbatimlines\beginofverbatimlinenumbering
+ \let\endofverbatimlines \endofverbatimlinenumbering
+ \fi
+ \fi}
+
+%D \macros
+%D {filename}
+%D
+%D Typesetting filenames in monospaced fonts is possible with
+%D
+%D \starttyping
+%D \filename{here/there/filename.suffix}
+%D \stoptyping
+%D
+%D The definition is not that spectacular.
+
+\unexpanded\def\filename#1{{\tttf\hyphenatedfilename{#1}}}
+
+%D \macros
+%D {verbatim}
+%d
+%D And a bonus macro, an unexpanded detokenize:
+
+\unexpanded\def\verbatim#1{\detokenize{#1}}
+
+%D The setups for display verbatim and file verbatim are shared. One can adapt the
+%D extra defined typing environments, but they also default to the values below.
+%D Watch the alternative escape character.
+
+% \tttf gives problems with {\tx \type...}
+% \tt\tf does not adapt to e.g. \bf
+
+\setuptyping
+ [\c!before=\blank,
+ \c!after=\blank,
+ %\c!keeptogether=yes, % this will become default (when tested enough)
+ %\c!bodyfont=,
+ %\c!color=,
+ \c!space=\v!off,
+ \c!lines=\v!no,
+ \c!page=\v!no,
+ \c!tab=\v!yes, % what is this: \s!ascii ?
+ \c!option=\v!none,
+ \c!text=\v!no,
+ \c!style=\tt,
+ \c!indentnext=\v!yes,
+ \c!margin=\zeropoint,
+ \c!evenmargin=\zeropoint,
+ \c!oddmargin=\zeropoint,
+ \c!blank=\v!line,
+ %\c!escape=, % yes | no | {START,STOP} | default when yes: {BTEX,ETEX}
+ \c!numbering=\v!no,
+ %\c!range=,
+ \c!start=1,
+ %\c!stop=,
+ \c!step=1,
+ %\c!continue=,
+ \c!strip=\v!no] % auto or number
+
+\definetyping[\v!typing]
+
+% the \zeropoint forces the number to the margin but also works ok in text
+
+\setuplinenumbering[\v!typing][\c!location=\v!left,\c!width=\zeropoint]
+
+\setuptyping [\v!file] [\s!parent=\??typing \v!typing] % we don't want \start..\stop overload
+\setuplinenumbering[\v!file] [\s!parent=\??linenumbering\v!typing]
+
+\setuptyping [\v!buffer][\s!parent=\??typing \v!file] % we don't want \start..\stop overload
+\setuplinenumbering[\v!buffer][\s!parent=\??linenumbering\v!file]
+
+%D The setups for inline verbatim default to:
+
+\setuptype
+ [\c!space=\v!off,
+ \c!lines=\v!no,
+ %\c!color=,
+ \c!style=\tt,
+ %\c!option=\v!normal,
+ \c!page=\v!no,
+ \c!tab=\v!yes,
+ \c!compact=\v!all]
+
+%D Buffers
+
+% [name] [settings] | [name] | [settings]
+
+% \unexpanded\def\typebuffer
+% {\dodoubleempty\buff_verbatim_type_buffer}
+
+\unexpanded\def\typebuffer
+ {\begingroup
+ \let\currenttyping\v!buffer
+ \dodoubleempty\buff_verbatim_type_buffer}
+
+\unexpanded\def\buff_verbatim_type_defined_buffer
+ {\dotripleempty\buff_verbatim_type_defined_buffer_indeed}
+
+\unexpanded\def\typedefinedbuffer[#1]%
+ {\buff_verbatim_type_defined_buffer[\v!buffer][\thedefinedbuffer{#1}]}%
+
+\appendtoks
+ \setuevalue{\e!type\currentbuffer}{\buff_verbatim_type_defined_buffer[\v!buffer][\currentdefinedbuffer]}%
+\to \everydefinebuffer
+
+\appendtoks % \e!buffer
+ \setuevalue{\e!type\currenttyping\v!buffer}{\buff_verbatim_type_buffer_class{\currenttyping}}%
+\to \everydefinetyping
+
+\unexpanded\def\buff_verbatim_type_buffer[#1][#2]%
+ {\ifsecondargument
+ \setupcurrenttyping[#2]%
+ \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings]
+ \orelse\iffirstargument
+ \ifcondition\validassignment{#1}%
+ \setupcurrenttyping[#1]%
+ \buff_verbatim_type_buffer_indeed\currenttyping\empty% [settings]
+ \else
+ \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name]
+ \fi
+ \else
+ \buff_verbatim_type_buffer_indeed\currenttyping\empty% []
+ \fi
+ \endgroup
+ \dorechecknextindentation}
+
+\unexpanded\def\buff_verbatim_type_buffer_class#1%
+ {\begingroup
+ \edef\currenttyping{#1}%
+ \dodoubleempty\buff_verbatim_type_buffer}
+
+\unexpanded\def\buff_verbatim_type_defined_buffer_indeed[#1][#2][#3]% category name settings
+ {\begingroup
+ \ifthirdargument
+ \setuptyping[#1][#3]%
+ \fi
+ \buff_verbatim_type_buffer_indeed{#1}{#2}%
+ \endgroup}
+
+\unexpanded\def\buff_verbatim_type_buffer_indeed#1#2% category name
+ {\edef\currenttyping{#1}%
+ \typingparameter\c!before
+ \startpacked[\v!blank]
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_initialize_typing_two
+ \dostarttaggedchained\t!verbatimblock{#1}\??typing
+ \beginofverbatimlines
+ \dostarttagged\t!verbatimlines\empty
+ \clf_typebuffer
+ name {#2}%
+ strip {\typingparameter\c!strip}%
+ range {\typingparameter\c!range}%
+ regime {\currentregime}%
+ tab {\typingparameter\c!tab}%
+ method {\p_buff_option}%
+ escape {\typingparameter\c!escape}%
+ nature {display}%
+ \relax
+ \dostoptagged
+ \endofverbatimlines
+ \dostoptagged
+ \stoppacked
+ \typingparameter\c!after
+ \dorechecknextindentation}
+
+\unexpanded\def\typeinlinebuffer
+ {\dontleavehmode
+ \begingroup
+ \let\buff_verbatim_type_buffer_indeed\buff_verbatim_type_buffer_indeed_inline
+ \let\setupcurrenttyping\setupcurrenttype % a terrible hack but it saves code
+ \let\currenttype\empty
+ \dodoubleempty\buff_verbatim_type_buffer}
+
+\unexpanded\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name
+ {\edef\currenttype{#1}%
+ \buff_verbatim_initialize_type_one
+ \dostarttaggedchained\t!verbatim\currenttype\??type
+ \clf_typebuffer
+ name {#2}%
+ strip {\v!yes}%
+ regime {\currentregime}%
+ method {\p_buff_option}%
+ nature {inline}% is default anyway
+ \relax
+ \dostoptagged}
+
+% get : before/after of buffer
+% typing : before/after of typing
+% process : no before/after (special case anyway)
+
+% the next one is obsolete (bad name and used nowhere) so if it stays
+% the name will change
+
+\unexpanded\def\processbuffer
+ {\writestatus{nota bene}{\string\processbuffer\space is obsolete}%
+ \dodoubleempty\buff_verbatim_process}
+
+\def\buff_verbatim_process[#1][#2]%
+ {\begingroup
+ \ifsecondargument
+ \setuptyping[\v!buffer][#2]%
+ \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings]
+ \orelse\iffirstargument
+ \ifcondition\validassignment{#1}%
+ \setuptyping[\v!buffer][#1]%
+ \buff_verbatim_process_indeed\v!buffer\empty% [settings]
+ \else
+ \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name]
+ \fi
+ \else
+ \buff_verbatim_process_indeed\v!buffer\empty% []
+ \fi
+ \endgroup}
+
+\def\buff_verbatim_process_indeed#1#2%
+ {\edef\currenttyping{#1}%
+ \clf_processbuffer
+ name {#2}%
+ strip {\typingparameter\c!strip}%
+ tab {\typingparameter\c!tab}%
+ % method {\p_buff_option}%
+ nature {direct}%
+ \relax}
+
+% so far for obsolete
+
+% line numbering, keep broken lines together
+
+\newcount\nofverbatimlines
+
+\unexpanded\def\buff_verbatim_begin_of_line
+ {\ifconditional\verbatimnumberinglines
+ \global\advance\nofverbatimlines\plusone
+ \attribute\verbatimlineattribute\nofverbatimlines
+ \fi
+ \noindent
+ \buff_verbatim_set_line_margin
+ \the\everyline % maybe also after starttagged
+ \strut % after starttagged, else break !
+ \dostarttagged\t!verbatimline\empty
+ }
+
+\unexpanded\def\buff_verbatim_end_of_line
+ {\dostoptagged
+ \obeyedline % still needed?
+ \par
+ \ifconditional\verbatimnumberinglines
+ \attribute\verbatimlineattribute\attributeunsetvalue
+ \fi}
+
+\unexpanded\def\buff_verbatim_empty_line
+ {\dostoptagged
+ \ifconditional\verbatimnumberinglines
+ \par\strut\par % this will be an option where we use a signal instead of a strut
+ \else
+ \blank[\typingparameter\c!blank]%
+ \fi
+ \dostarttagged\t!verbatimlines\empty}
+
+% hooks:
+
+\newcount \c_buff_verbatim_noflines
+\newcount \c_buff_verbatim_current
+\newconditional\c_buff_optimize_linebreaks
+
+ \def\doverbatimspace {\obeyedspace}
+
+\unexpanded\def\doinlineverbatimstart {}
+\unexpanded\def\doinlineverbatimstop {}
+\unexpanded\def\doinlineverbatimbeginline {}
+\unexpanded\def\doinlineverbatimnewline {\obeyedspace}
+\unexpanded\def\doinlineverbatimemptyline {\obeyedspace}
+
+\unexpanded\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone
+ \buff_verbatim_begin_of_line}
+\unexpanded\def\dodisplayverbatimstop {\buff_verbatim_end_of_line}
+\unexpanded\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone
+ \buff_verbatim_begin_of_line}
+\unexpanded\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line
+ \par
+ \ifconditional\c_buff_optimize_linebreaks
+ \buff_verbatim_inject_breaks
+ \fi}
+\unexpanded\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line}
+
+\unexpanded\def\buff_verbatim_inject_breaks
+ {\ifnum\c_buff_verbatim_current=\plusone
+ \nobreak
+ \orelse\ifnum\c_buff_verbatim_noflines=\plusthree
+ \nobreak
+ \orelse\ifnum\c_buff_verbatim_current=\numexpr\c_buff_verbatim_noflines-\plusone\relax
+ \nobreak
+ \fi}
+
+\unexpanded\def\dodisplayverbatiminitialize#1%
+ {\forgetparindent % maybe more
+ \c_buff_verbatim_noflines#1\relax
+ \c_buff_verbatim_current\zerocount}
+
+\loadmarkfile{buff-imp-default} % preloaded as otherwise spurious spaces inline due to loading
+\loadmarkfile{buff-imp-nested} % preloaded as otherwise spurious spaces inline due to loading
+\loadmarkfile{buff-imp-escaped} % for completeness
+
+%D To be considered:
+
+% \installcorenamespace{visualizer}
+%
+% \installcommandhandler \??visualizer {visualizer} \??visualizer
+%
+% \appendtoks
+% \setuevalue{\currentvisualizer}{\buff_verbatim_visualize{\currentvisualizer}}%
+% \to \everydefinevisualizer
+%
+% \unexpanded\def\buff_verbatim_visualize#1%
+% {\bgroup
+% \def\currentvisualizer{#1}%
+% \usevisualizerstyleandcolor\c!style\c!color
+% \let\next}
+
+\appendtoks
+ %def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize
+ \def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize
+ \def\tex #1{\letterbackslash#1}%
+\to \everysimplifycommands
+
+\stopcontextdefinitioncode
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index ff4f5e3b1..026d78c0d 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -746,7 +746,7 @@ local s_cldl_argument_e = "}"
-- local s_cldl_argument_b = "{"
-- local s_cldl_argument_f = "{ "
-local t_cldl_luafunction = createtoken("luafunctioncall")
+local t_cldl_luafunction = newtoken("luafunctioncall",0)
local lua_expandable_call_token_code = token.command_id and token.command_id("lua_expandable_call")
local function writer(parent,command,...) -- already optimized before call
diff --git a/tex/context/base/mkiv/colo-ini.mkiv b/tex/context/base/mkiv/colo-ini.mkiv
index c5639f44a..7e78f0e01 100644
--- a/tex/context/base/mkiv/colo-ini.mkiv
+++ b/tex/context/base/mkiv/colo-ini.mkiv
@@ -37,16 +37,15 @@
\unprotect
-%D In \MKIV\ we have independent color, colorspace and transparency
-%D but I'm still not sure if I keep it that way as it's probably more
-%D efficient to combine them (less attributes and finalizing). If
-%D it becomes a bottleneck we can set up a more complex system
-%D with one shared attribute for colorspace, color and transparency.
+%D In \MKIV\ we have independent color, colorspace and transparency but I'm still
+%D not sure if I keep it that way as it's probably more efficient to combine them
+%D (less attributes and finalizing). If it becomes a bottleneck we can set up a more
+%D complex system with one shared attribute for colorspace, color and transparency.
%D
-%D When typesetting for paper, we prefer using the \CMYK\ color space,
-%D but for on||screen viewing we prefer \RGB\ (the previous
-%D implementation supported only this scheme). Independant of such
-%D specifications, we support some automatic conversions:
+%D When typesetting for paper, we prefer using the \CMYK\ color space, but for
+%D on||screen viewing we prefer \RGB\ (the previous implementation supported only
+%D this scheme). Independant of such specifications, we support some automatic
+%D conversions:
%D
%D \startitemize[packed]
%D \item convert all colors to \RGB
@@ -111,8 +110,7 @@
%D \macros
%D {startcolor,stopcolor,color,graycolor}
%D
-%D The local and global commands are here just for compatibility
-%D with \MKII.
+%D The local and global commands are here just for compatibility with \MKII.
%D
%D \showsetup{startcolor}
%D
@@ -274,11 +272,11 @@
%D
%D \showsetup{usecolors}
%D
-%D Some default colors are specified in \type {colo-imp-rgb},
-%D which is loaded into the format by default.
+%D Some default colors are specified in \type {colo-imp-rgb}, which is loaded into
+%D the format by default.
%D
-%D Some demo palets and groups are defined in \type {colo-imp-dem}
-%D which can be loaded with:
+%D Some demo palets and groups are defined in \type {colo-imp-dem} which can be
+%D loaded with:
%D
%D \starttyping
%D \usecolors[dem]
@@ -371,33 +369,27 @@
{\attribute\colorattribute \c_colo_saved_attribute_color
\attribute\transparencyattribute\c_colo_saved_attribute_transparency}
-%D In this documentation we will not go into too much details
-%D on palets. Curious users can find more information on this
-%D topic in \from[use of color].
+%D In this documentation we will not go into too much details on palets. Curious
+%D users can find more information on this topic in \from[use of color].
%D
-%D At the moment we implemented color in \CONTEXT\ color
-%D printing was not yet on the desktop. In spite of this lack our
-%D graphics designer made colorfull illustrations. When printed
-%D on a black and white printer, distinctive colors can come
-%D out equally gray. We therefore decided to use only colors
-%D that were distinctive in colors as well as in black and
-%D white print.
+%D At the moment we implemented color in \CONTEXT\ color printing was not yet on the
+%D desktop. In spite of this lack our graphics designer made colorfull
+%D illustrations. When printed on a black and white printer, distinctive colors can
+%D come out equally gray. We therefore decided to use only colors that were
+%D distinctive in colors as well as in black and white print.
%D
-%D Although none of the graphic packages we used supported
-%D logical colors and global color redefition, we build this
-%D support into \CONTEXT. This enabled us to experiment and
-%D also prepared us for the future.
+%D Although none of the graphic packages we used supported logical colors and global
+%D color redefition, we build this support into \CONTEXT. This enabled us to
+%D experiment and also prepared us for the future.
%D \macros
%D {definepalet}
%D
-%D Colors are grouped in palets. The colors in such a palet can
-%D have colorful names, but best is to use names that specify
-%D their use, like {\em important} or {\em danger}. As a sort
-%D of example \CONTEXT\ has some palets predefined,
-%D like:\footnote{At the time I wrote the palet support, I was
-%D reading 'A hort history of time' of S.~Hawkins, so that's
-%D why we stuck to quarks.}
+%D Colors are grouped in palets. The colors in such a palet can have colorful names,
+%D but best is to use names that specify their use, like {\em important} or {\em
+%D danger}. As a sort of example \CONTEXT\ has some palets predefined,
+%D like:\footnote{At the time I wrote the palet support, I was reading 'A hort
+%D history of time' of S.~Hawkins, so that's why we stuck to quarks.}
%D
%D \starttyping
%D \definepalet
@@ -424,8 +416,8 @@
%D \getbuffer[palet]
%D \stoplinecorrection
%D
-%D This bar shows both the color and gray alternatives of the
-%D palet components (not visible in black and white print).
+%D This bar shows both the color and gray alternatives of the palet components (not
+%D visible in black and white print).
%D
%D When needed, one can copy a palet by saying:
%D
@@ -433,8 +425,8 @@
%D \definepalet [TEXcolorpretty] [colorpretty]
%D \stoptyping
%D
-%D This saves us some typing in for instance the modules that
-%D deal with pretty verbatim typesetting.
+%D This saves us some typing in for instance the modules that deal with pretty
+%D verbatim typesetting.
\installcorenamespace{paletlist}
\installcorenamespace{paletsize}
@@ -538,8 +530,7 @@
\processcommacommand[\lastnamedcs]{\colo_palets_define_one{#1}}%
\fi}
-%D Instead of refering to colors, one can also directly specify
-%D a color:
+%D Instead of refering to colors, one can also directly specify a color:
%D
%D \starttyping
%D \definepalet[test][xx=green]
@@ -549,8 +540,8 @@
%D \macros
%D {setuppalet}
%D
-%D Colors are taken from the current palet, if defined.
-%D Setting the current palet is done by:
+%D Colors are taken from the current palet, if defined. Setting the current palet is
+%D done by:
%D
%D \showsetup{setuppalet}
@@ -642,8 +633,8 @@
%D \macros
%D {showcolor}
%D
-%D But let's not forget that we also have the more traditional
-%D non||related colors. These show up after:
+%D But let's not forget that we also have the more traditional non||related colors.
+%D These show up after:
%D
%D \starttyping
%D \showcolor [name]
@@ -655,8 +646,8 @@
\fetchruntimecommand \showcolor \f!colo_run
-%D It would make sense to put the following code in \type
-%D {colo-mps}, but it it rather low level.
+%D It would make sense to put the following code in \type {colo-mps}, but it it
+%D rather low level.
%D \macros
%D {negatecolorcomponent,negatedcolorcomponent}
@@ -687,8 +678,8 @@
%D \macros
%D {MPcolor}
%D
-%D A very special macro is \type{\MPcolor}. This one can be
-%D used to pass a \CONTEXT\ color to \METAPOST.
+%D A very special macro is \type{\MPcolor}. This one can be used to pass a \CONTEXT\
+%D color to \METAPOST.
%D
%D \starttyping
%D \MPcolor{my own red}
@@ -697,15 +688,13 @@
%D This macro returns \METAPOST\ code that represents the
%D color.
%D
-%D For the moment we keep the next downward compatibility
-%D switch, i.e.\ expanded colors. However, predefined colors
-%D and palets are no longer expanded (which is what I wanted
-%D in the first place).
+%D For the moment we keep the next downward compatibility switch, i.e.\ expanded
+%D colors. However, predefined colors and palets are no longer expanded (which is
+%D what I wanted in the first place).
%D
-%D In \MKIV\ we don't support color separation as we might now
-%D assume that printing houses have the right programs to do
-%D it themselves. If it's ever needed in \MKIV\ It is relatively
-%D easy to support it in the backend code.
+%D In \MKIV\ we don't support color separation as we might now assume that printing
+%D houses have the right programs to do it themselves. If it's ever needed in \MKIV\
+%D It is relatively easy to support it in the backend code.
% todo: palets in definecolor
% todo: {\red xx} vs \red{xx}
@@ -755,12 +744,12 @@
\fi
\fi}
-% Currently in mkiv transparency is implemented independent of color. This costs
-% a bit more processing time but gives the possibility to apply transparency
-% independently in the future. Is this useful? If not we may as well combine them
-% again in the future. By coupling we are downward compatible. When we decouple we
-% need to do more tricky housekeeping (e.g. persist color independent transparencies
-% when color bound ones are nil.
+%D Currently in mkiv transparency is implemented independent of color. This costs a
+%D bit more processing time but gives the possibility to apply transparency
+%D independently in the future. Is this useful? If not we may as well combine them
+%D again in the future. By coupling we are downward compatible. When we decouple we
+%D need to do more tricky housekeeping (e.g. persist color independent
+%D transparencies when color bound ones are nil.
% Since we couple definitions, we could stick to one test. Todo. Same for mpcolor.
@@ -953,10 +942,9 @@
\unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
\fi}
-% Spotcolors used setxvalue but that messes up currentcolor
-% and probably no global is needed either but they are global
-% at the lua end (true argument) so we keep that if only because
-% spot colors often are a document wide property
+%D Spotcolors used setxvalue but that messes up currentcolor and probably no global
+%D is needed either but they are global at the lua end (true argument) so we keep
+%D that if only because spot colors often are a document wide property
\def\colo_basics_define_spot[#1][#2][#3]%
{\clf_definespotcolorglobal{#1}{#2}{#3}%
@@ -1008,8 +996,8 @@
%
% \definecolor[one][two]
%
-% only color one is actually defined and two is not seen at the
-% \LUA\ end. This means that this doesn't work:
+% Only color one is actually defined and two is not seen at the \LUA\ end. This
+% means that this doesn't work:
%
% \definecolor[ColorA][red]
% \definecolor[ColorB][.5(ColorA)]
@@ -1093,9 +1081,8 @@
%D \macros
%D {doifcolorelse, doifcolor}
%D
-%D Switching to a color is done by means of the following
-%D command. Later on we will explain the use of palets. We
-%D define ourselves a color conditional first.
+%D Switching to a color is done by means of the following command. Later on we will
+%D explain the use of palets. We define ourselves a color conditional first.
\def\doifelsecolor#1%
{\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
@@ -1120,13 +1107,11 @@
%D \macros
%D {startregistercolor,stopregistercolor,permitcolormode}
%D
-%D If you only want to register a color, the switch \type
-%D {\ifpermitcolormode} can be used. That way the nested
-%D colors know where to go back to.
+%D If you only want to register a color, the switch \type {\ifpermitcolormode} can
+%D be used. That way the nested colors know where to go back to.
%D
-%D We use these macros for implementing text colors
-%D (actually, the first application was in foreground
-%D colors).
+%D We use these macros for implementing text colors (actually, the first application
+%D was in foreground colors).
%D
%D \starttyping
%D \starttextcolor[red]
@@ -1292,8 +1277,8 @@
%D \macros
%D {colorvalue, grayvalue}
%D
-%D We can typeset the color components using \type{\colorvalue} and
-%D \type{\grayvalue}. The commands:
+%D We can typeset the color components using \type {\colorvalue} and \type
+%D {\grayvalue}. The commands:
%D
%D \startbuffer
%D color value of SomeKindOfRed: \colorvalue{SomeKindOfRed} \crlf
@@ -1370,8 +1355,8 @@
%D \macros
%D {forcecolorhack}
%D
-%D We can out this in front of (for instance) a special and so force color
-%D to be applied (only glyphs, rules and leaders are handled).
+%D We can out this in front of (for instance) a special and so force color to be
+%D applied (only glyphs, rules and leaders are handled).
%D
%D \startbuffer
%D \framed
diff --git a/tex/context/base/mkiv/colo-ini.mkxl b/tex/context/base/mkiv/colo-ini.mkxl
new file mode 100644
index 000000000..53d45f943
--- /dev/null
+++ b/tex/context/base/mkiv/colo-ini.mkxl
@@ -0,0 +1,1399 @@
+%D \module
+%D [ file=colo-ini,
+%D version=2007.08.08,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D We need to clean this up further but first we have to make sure that mkiv
+%D code works ok.
+
+\writestatus{loading}{ConTeXt Color Macros / Initialization}
+
+%D Todo: move color space in color attribute (last two bits)
+
+%D This module implements color. Since \MKII\ and \MKIV\ use a completely
+%D different approach, this module only implements a few generic mechanisms.
+
+\installcorenamespace{color}
+\installcorenamespace{colorattribute}
+\installcorenamespace{transparencyattribute}
+\installcorenamespace{colorsetter}
+\installcorenamespace{transparencysetter}
+\installcorenamespace{colorpaletspecification}
+\installcorenamespace{colorpalet}
+\installcorenamespace{colorstack}
+\installcorenamespace{colorconversions}
+\installcorenamespace{colornumber}
+
+\registerctxluafile{colo-ini}{}
+\registerctxluafile{colo-icc}{}
+
+\unprotect
+
+%D In \MKIV\ we have independent color, colorspace and transparency but I'm still
+%D not sure if I keep it that way as it's probably more efficient to combine them
+%D (less attributes and finalizing). If it becomes a bottleneck we can set up a more
+%D complex system with one shared attribute for colorspace, color and transparency.
+%D
+%D When typesetting for paper, we prefer using the \CMYK\ color space, but for
+%D on||screen viewing we prefer \RGB\ (the previous implementation supported only
+%D this scheme). Independant of such specifications, we support some automatic
+%D conversions:
+%D
+%D \startitemize[packed]
+%D \item convert all colors to \RGB
+%D \item convert all colors to \CMYK
+%D \item convert all colors to gray scales
+%D \stopitemize
+%D
+%D These options are communicated by means of:
+
+\newconditional\c_colo_rgb_supported
+\newconditional\c_colo_cmyk_supported
+\newconditional\c_colo_spot_supported % backend driven
+\newconditional\c_colo_convert_gray \settrue\c_colo_convert_gray
+\newconditional\c_colo_enabled
+\newconditional\c_colo_expanded
+
+\let\m_colo_weight_gray\v!yes
+
+\let\currentcolormodel \empty
+\let\currentcolorname \empty
+\let\currentcolorpalet \empty
+\let\currentcolorprefix\empty % \currentcolorpalet:
+
+%D \macros
+%D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor,
+%D definetransparency}
+%D
+%D \starttyping
+%D \definecolor [blue] [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
+%D \definecolor [yellow] [c=0,m=.28,y=1,k=.06] % pantone pms 124 uncoated m
+%D
+%D \definespotcolor [blue-100] [blue] [p=1]
+%D \definespotcolor [yellow-100] [yellow] [p=1]
+%D
+%D \definemultitonecolor [pdftoolscolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
+%D
+%D \defineprocesscolor[myred][r=.5]
+%D \defineprocesscolor[myredish][red][a=1,t=.5]
+%D
+%D \blackrule[color=myred,width=\hsize,height=1cm] \par
+%D \blackrule[color=myredish,width=\hsize,height=1cm]
+%D
+%D \useexternalfigure[demofig][mill.png][object=no]
+%D
+%D \startcombination[4*1]
+%D {\externalfigure[demofig]} {no color}
+%D {\externalfigure[demofig][color=pdftoolscolor]} {indexed duotone}
+%D {\externalfigure[demofig][color=blue-100]} {spot color}
+%D {\externalfigure[demofig][color=yellow-100]} {spot color}
+%D \stopcombination
+%D \stoptyping
+
+\unexpanded\def\definecolor {\dodoubleargument\colo_basics_define}
+\unexpanded\def\defineglobalcolor {\dodoubleargument\colo_basics_define_global}
+\unexpanded\def\defineprocesscolor {\dotripleargument\colo_basics_define_process}
+\unexpanded\def\definenamedcolor {\dodoubleargument\colo_basics_define_named}
+\unexpanded\def\definespotcolor {\dotripleargument\colo_basics_define_spot}
+\unexpanded\def\definemultitonecolor {\doquadrupleempty\colo_basics_define_multitone}
+\unexpanded\def\definetransparency {\dodoubleargument\colo_basics_define_transpancy}
+\unexpanded\def\defineglobaltransparency{\dodoubleargument\colo_basics_define_transpancy_global}
+
+%D \macros
+%D {startcolor,stopcolor,color,graycolor}
+%D
+%D The local and global commands are here just for compatibility with \MKII.
+%D
+%D \showsetup{startcolor}
+%D
+%D The simple color commands are:
+%D
+%D \showsetup{color}
+%D \showsetup{graycolor}
+
+%D We expect sane behaviour in \MKIV\ so we don't used grouped command any
+%D longer.
+
+% \testfeatureonce{100000}{\color[red]{}} % 1.046 => 0.541
+
+\let\g_color\empty
+\let\g_style\empty
+
+\unexpanded\def\switchtocolor[#1]{\begincsname#1\endcsname}
+
+% transparency
+
+\unexpanded\def\transparent[#1]%
+ {\bgroup
+ \edef\currenttransparencyname{#1}%
+ % the \relax catches a non existent csname
+ \ifx\currenttransparencyname\v!reset
+ \attribute\transparencyattribute\attributeunsetvalue
+ \else
+ \begincsname\??transparencysetter\currenttransparencyname\endcsname\relax
+ \fi
+ \let\nexttoken}
+
+\unexpanded\def\starttransparent[#1]%$
+ {\begingroup
+ \edef\currenttransparencyname{#1}%
+ \ifx\currenttransparencyname\v!reset
+ \attribute\transparencyattribute\attributeunsetvalue
+ \else
+ \begincsname\??transparencysetter\currenttransparencyname\endcsname\relax
+ \fi}
+
+\unexpanded\def\stoptransparent
+ {\endgroup}
+
+% color
+
+\unexpanded\def\coloronly[#1]%
+ {\bgroup
+ \edef\currentcolorname{#1}%
+ \ifx\currentcolorprefix\empty
+ \colo_helpers_activate_nop_only
+ \else
+ \colo_helpers_activate_yes_only
+ \fi
+ \let\nexttoken}
+
+\unexpanded\def\startcoloronly[#1]%$
+ {\begingroup
+ \edef\currentcolorname{#1}%
+ \ifx\currentcolorprefix\empty
+ \colo_helpers_activate_nop_only
+ \else
+ \colo_helpers_activate_yes_only
+ \fi}
+
+\unexpanded\def\stopcoloronly
+ {\endgroup}
+
+% color + transparency
+
+\unexpanded\def\color[#1]%
+ {\bgroup
+ \edef\currentcolorname{#1}%
+ \ifx\currentcolorprefix\empty
+ \colo_helpers_activate_nop
+ \else
+ \colo_helpers_activate_yes
+ \fi
+ \let\nexttoken}
+
+\unexpanded\def\graycolor[#1]%
+ {\bgroup
+ \colo_helpers_set_model\s!gray\colo_helpers_activate{#1}%
+ \let\nexttoken}
+
+\unexpanded\def\startcolor[#1]%$
+ {\begingroup
+ \edef\currentcolorname{#1}%
+ \ifx\currentcolorprefix\empty
+ \colo_helpers_activate_nop
+ \else
+ \colo_helpers_activate_yes
+ \fi}
+
+\unexpanded\def\stopcolor
+ {\endgroup}
+
+\unexpanded\def\colored[#1]%
+ {\bgroup
+ \colo_basics_defined_and_activated{#1}%
+ \let\nexttoken}
+
+\unexpanded\def\fastcolored[#1]#2%
+ {\begingroup % is this command still needed?
+ \colo_basics_defined_and_activated{#1}%
+ #2%
+ \endgroup}
+
+\unexpanded\def\directcolored[#1]%
+ {\colo_basics_defined_and_activated{#1}}
+
+\unexpanded\def\fastcolor [#1]#2%
+ {\begingroup % is this command still needed?
+ \edef\currentcolorname{#1}%
+ \ifx\currentcolorprefix\empty
+ \colo_helpers_activate_nop
+ \else
+ \colo_helpers_activate_yes
+ \fi
+ #2%
+ \endgroup}
+
+\unexpanded\def\directcolor[#1]%
+ {\edef\currentcolorname{#1}%
+ \ifx\currentcolorprefix\empty
+ \colo_helpers_activate_nop
+ \else
+ \colo_helpers_activate_yes
+ \fi}
+
+%D The following command is obsolete:
+
+\unexpanded\def\startcolorpage {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}
+\unexpanded\def\stopcolorpage {\stopcolor}
+
+\unexpanded\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ...
+ {\begingroup
+ \colo_helpers_activate{#1}%
+ \normalexpanded{\endgroup\edef\noexpand#2%
+ {\ifnum\attribute\colorattribute=\attributeunsetvalue\else\number\attribute\colorattribute\fi}}}
+
+\let\grey\graycolor % these macros are only used in tracing
+
+%D \macros
+%D {startcurrentcolor,stopcurrentcolor}
+
+\unexpanded\def\startcurrentcolor{\startcolor[\outercolorname]}
+\unexpanded\def\stopcurrentcolor {\stopcolor}
+
+%D \macros
+%D {setupcolor}
+%D
+%D Color definitions can be grouped in files with the name:
+%D
+%D \starttyping
+%D colo-imp-tag.tex
+%D \stoptyping
+%D
+%D Loading such a file is done by:
+%D
+%D \showsetup{usecolors}
+%D
+%D Some default colors are specified in \type {colo-imp-rgb}, which is loaded into
+%D the format by default.
+%D
+%D Some demo palets and groups are defined in \type {colo-imp-dem} which can be
+%D loaded with:
+%D
+%D \starttyping
+%D \usecolors[dem]
+%D \stoptyping
+
+\unexpanded\def\startcolorset[#1]{\clf_startcolorset{#1}}
+\unexpanded\def\stopcolorset {\clf_stopcolorset}
+\unexpanded\def\usecolors [#1]{\clf_usecolors{#1}}
+
+\let\setupcolor\usecolors
+
+\installsetuponlycommandhandler \??color {colors}
+
+\let\colo_helpers_show_message\gobblethreearguments
+
+% \newtoks\everysetupcolors
+
+\let\v_colo_freeze_state\s!false
+
+\setvalue{\??colorconversions\v!yes}%
+ {\settrue \c_colo_convert_gray}
+
+\setvalue{\??colorconversions\v!always}%
+ {\settrue \c_colo_convert_gray
+ \setfalse\c_colo_rgb_supported
+ \setfalse\c_colo_cmyk_supported}
+
+\appendtoks
+ %
+ \doifelse{\directcolorsparameter\c!spot }\v!yes \settrue \setfalse\c_colo_spot_supported
+ \doifelse{\directcolorsparameter\c!expansion}\v!yes \settrue \setfalse\c_colo_expanded
+ \doifelse{\directcolorsparameter\c!rgb }\v!yes \settrue \setfalse\c_colo_rgb_supported
+ \doifelse{\directcolorsparameter\c!cmyk }\v!yes \settrue \setfalse\c_colo_cmyk_supported
+ \doifelse{\directcolorsparameter\c!state }\v!start\settrue \setfalse\c_colo_enabled
+ %
+ \edef\m_colo_weight_gray{\directcolorsparameter\c!factor}%
+ %
+ \ifconditional\c_colo_expanded
+ \let\v_colo_freeze_state\s!true
+ \else
+ \let\v_colo_freeze_state\s!false
+ \fi
+ %
+ \setfalse\c_colo_convert_gray
+ \begincsname\??colorconversions\directcolorsparameter\c!conversion\endcsname
+ % too often:
+ \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors{10}\v!rgb \fi
+ \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors{10}\v!cmyk\fi
+ \colo_helpers_set_current_model
+ \ifproductionrun
+ \edef\p_pagecolormodel{\directcolorsparameter\c!pagecolormodel}%
+ \clf_setpagecolormodel{\ifx\p_pagecolormodel\v!auto\currentcolormodel\else\p_pagecolormodel\fi}%
+ \fi
+\to \everysetupcolors
+
+\appendtoks
+ \setupcolors[\c!state=\v!start]%
+ \clf_enablecolor % this can as well happen when
+ \clf_enabletransparency % the handler is defined in lua
+ \let\colo_helpers_show_message\showmessage
+\to \everyjob
+
+%D We provide stacking independent of grouping.
+
+\newcount\c_colo_nesting
+
+\unexpanded\def\pushcolor[#1]%
+ {\global\advance\c_colo_nesting\plusone
+ \expandafter\edef\csname\??colorstack\number\c_colo_nesting\endcsname
+ {\attribute\colormodelattribute \the\attribute\colormodelattribute
+ \attribute\colorattribute \the\attribute\colorattribute
+ \attribute\transparencyattribute\the\attribute\transparencyattribute
+ \relax}% stack
+ \colo_helpers_activate{#1}}
+
+\unexpanded\def\popcolor
+ {\csname\??colorstack\number\c_colo_nesting\endcsname
+ \global\advance\c_colo_nesting\minusone}
+
+% a simple one: assumes grouping
+
+\newcount\c_colo_saved_attribute_color
+\newcount\c_colo_saved_attribute_transparency
+
+\unexpanded\def\savecolor
+ {\c_colo_saved_attribute_color \attribute\colorattribute
+ \c_colo_saved_attribute_transparency\attribute\transparencyattribute}
+
+\unexpanded\def\restorecolor
+ {\attribute\colorattribute \c_colo_saved_attribute_color
+ \attribute\transparencyattribute\c_colo_saved_attribute_transparency}
+
+%D In this documentation we will not go into too much details on palets. Curious
+%D users can find more information on this topic in \from[use of color].
+%D
+%D At the moment we implemented color in \CONTEXT\ color printing was not yet on the
+%D desktop. In spite of this lack our graphics designer made colorfull
+%D illustrations. When printed on a black and white printer, distinctive colors can
+%D come out equally gray. We therefore decided to use only colors that were
+%D distinctive in colors as well as in black and white print.
+%D
+%D Although none of the graphic packages we used supported logical colors and global
+%D color redefition, we build this support into \CONTEXT. This enabled us to
+%D experiment and also prepared us for the future.
+
+%D \macros
+%D {definepalet}
+%D
+%D Colors are grouped in palets. The colors in such a palet can have colorful names,
+%D but best is to use names that specify their use, like {\em important} or {\em
+%D danger}. As a sort of example \CONTEXT\ has some palets predefined,
+%D like:\footnote{At the time I wrote the palet support, I was reading 'A hort
+%D history of time' of S.~Hawkins, so that's why we stuck to quarks.}
+%D
+%D \starttyping
+%D \definepalet
+%D [alfa]
+%D [ top=rood:7,
+%D bottom=groen:6,
+%D up=blauw:5,
+%D down=cyaan:4,
+%D strange=magenta:3,
+%D charm=geel:2]
+%D \stoptyping
+%D
+%D It's formal definition is:
+%D
+%D \showsetup{definepalet}
+%D
+%D Visualized, such a palet looks like:
+%D
+%D \startbuffer[palet]
+%D \showpalet [alfa] [horizontal,name,number,value]
+%D \stopbuffer
+%D
+%D \startlinecorrection
+%D \getbuffer[palet]
+%D \stoplinecorrection
+%D
+%D This bar shows both the color and gray alternatives of the palet components (not
+%D visible in black and white print).
+%D
+%D When needed, one can copy a palet by saying:
+%D
+%D \starttyping
+%D \definepalet [TEXcolorpretty] [colorpretty]
+%D \stoptyping
+%D
+%D This saves us some typing in for instance the modules that deal with pretty
+%D verbatim typesetting.
+
+\installcorenamespace{paletlist}
+\installcorenamespace{paletsize}
+
+\let\m_colo_palet\relax
+\let\c_colo_palet\relax
+
+\def\colo_palet_allocate#1%
+ {\expandafter\let \csname\??paletlist#1\endcsname\empty
+ \expandafter\newcount\csname\??paletsize#1\endcsname}
+
+\def\colo_palet_prepare#1%
+ {\edef\colo_palet_name{#1}%
+ \ifcsname\??paletlist\colo_palet_name\endcsname
+ \csname\??paletsize\colo_palet_name\endcsname\zerocount
+ \else
+ \colo_palet_allocate\colo_palet_name
+ \fi
+ \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}%
+ \expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname}
+
+\def\colo_palet_extend#1%
+ {\addtocommalist{#1}\m_colo_palet
+ \expandafter\let\csname\??paletlist\colo_palet_name\endcsname\m_colo_palet
+ \advance\c_colo_palet\plusone}
+
+\unexpanded\def\doifelsecolorpalet#1%
+ {\ifcsname\??paletlist#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\paletlist\empty
+\let\paletsize\!!zerocount
+
+\unexpanded\def\getpaletlist[#1]%
+ {\edef\paletlist{\begincsname\??paletlist#1\endcsname}}
+
+\unexpanded\def\getpaletsize[#1]%
+ {\ifcsname\??paletsize#1\endcsname
+ \edef\paletsize{\the\lastnamedcs}%
+ \else
+ \let\paletsize\!!zerocount
+ \fi}
+
+\unexpanded\def\definepalet
+ {\dotripleempty\colo_palets_define}
+
+\def\colo_palets_define
+ {\ifthirdargument
+ \expandafter\colo_palets_define_b
+ \else
+ \expandafter\colo_palets_define_a
+ \fi}
+
+\unexpanded\def\colo_palets_define_a[#1][#2][#3]%
+ {\colo_palet_prepare{#1}%
+ \ifcondition\validassignment{#2}%
+ \setevalue{\??colorpaletspecification#1}{#2}%
+ \processcommalist[#2]{\colo_palets_define_one{#1}}%
+ \orelse\ifcsname\??colorpaletspecification#2\endcsname
+ \normalexpanded{\colo_palets_define[#1][\lastnamedcs]}%
+ \fi}
+
+\unexpanded\def\colo_palets_define_b[#1][#2][#3]%
+ {\colo_palet_prepare{#1}%
+ \setevalue{\??colorpaletspecification#1}{#2}%
+ \colo_palet_extend{#2}%
+ \colo_palets_define_assign{#1}{#2}{#3}}
+
+\def\colo_palets_define_one#1#2% get rid of { }
+ {\ifcondition\validassignment{#2}% catch empty entries
+ \colo_palets_define_two{#1}[#2]%
+ \else
+ \colo_palets_define_three{#1}{#2}%
+ \fi}
+
+\def\colo_palets_define_two#1[#2=#3]%
+ {\colo_palet_extend{#2}%
+ \colo_palets_define_set{#1}{#2}{#3}}%
+
+\def\colo_palets_define_three#1#2%
+ {\ifcsname\??colorpaletspecification#2\endcsname
+ \processcommacommand[\lastnamedcs]{\colo_palets_define_one{#1}}%
+ \fi}
+
+%D Instead of refering to colors, one can also directly specify a color:
+%D
+%D \starttyping
+%D \definepalet[test][xx=green]
+%D \definepalet[test][xx={y=.4}]
+%D \stoptyping
+
+%D \macros
+%D {setuppalet}
+%D
+%D Colors are taken from the current palet, if defined. Setting the current palet is
+%D done by:
+%D
+%D \showsetup{setuppalet}
+
+\newtoks\everysetuppalet
+
+\unexpanded\def\setuppalet
+ {\dosingleempty\colo_palets_setup}
+
+% \newtoks\t_colo_prefix % used in mp interface
+
+\def\colo_palets_setup[#1]%
+ {\edef\currentcolorpalet{#1}%
+ \ifx\currentcolorpalet\empty
+ % seems to be a reset
+ \let\currentcolorprefix\empty
+ %\t_colo_prefix\emptytoks
+ \orelse\ifcsname\??paletlist\currentcolorpalet\endcsname
+ \edef\currentcolorprefix{#1:}%
+ %\t_colo_prefix\expandafter{\currentcolorprefix}%
+ \else
+ \colo_helpers_show_message\m!colors7\currentcolorpalet
+ \let\currentcolorpalet\empty
+ \let\currentcolorprefix\empty
+ %\t_colo_prefix\emptytoks
+ \fi
+ \the\everysetuppalet
+ \colo_helpers_initialize_maintextcolor}
+
+%D \macros
+%D {showpalet}
+%D
+%D The previous visualization was typeset with:
+%D
+%D \typebuffer[palet]
+%D
+%D This commands is defined as:
+%D
+%D \showsetup{showpalet}
+
+\fetchruntimecommand \showpalet \f!colo_run
+
+%D \macros
+%D {showcolorcomponents}
+%D
+%D \starttyping
+%D \showcolorcomponents[color-1,color-2]
+%D \stoptyping
+
+\fetchruntimecommand \showcolorcomponents \f!colo_run
+
+%D \macros
+%D {comparepalet}
+%D
+%D There are some more testing macros available:
+%D
+%D \startbuffer
+%D \comparepalet [alfa]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows the palet colors against a background:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D The formal definition is:
+%D
+%D \showsetup{comparepalet}
+
+\fetchruntimecommand \comparepalet \f!colo_run
+
+%D \macros
+%D {showcolor}
+%D
+%D But let's not forget that we also have the more traditional non||related colors.
+%D These show up after:
+%D
+%D \starttyping
+%D \showcolor [name]
+%D \stoptyping
+%D
+%D Where \type{name} for instance can be \type{rgb}.
+%D
+%D \showsetup{showcolor}
+
+\fetchruntimecommand \showcolor \f!colo_run
+
+%D It would make sense to put the following code in \type {colo-mps}, but it it
+%D rather low level.
+
+%D \macros
+%D {negatecolorcomponent,negatedcolorcomponent}
+%D
+%D These speak for themselves. See \type {colo-ext} for usage.
+
+\unexpanded\def\negatecolorcomponent#1% #1 = \macro
+ {\edef#1{\clf_negatecolorcomponent{#1}}}
+
+\def\negatedcolorcomponent#1%
+ {\clf_negatecolorcomponent{#1}}
+
+%D \macros
+%D {MPcolor}
+%D
+%D A very special macro is \type{\MPcolor}. This one can be used to pass a \CONTEXT\
+%D color to \METAPOST.
+%D
+%D \starttyping
+%D \MPcolor{my own red}
+%D \stoptyping
+%D
+%D This macro returns \METAPOST\ code that represents the
+%D color.
+%D
+%D For the moment we keep the next downward compatibility switch, i.e.\ expanded
+%D colors. However, predefined colors and palets are no longer expanded (which is
+%D what I wanted in the first place).
+%D
+%D In \MKIV\ we don't support color separation as we might now assume that printing
+%D houses have the right programs to do it themselves. If it's ever needed in \MKIV\
+%D It is relatively easy to support it in the backend code.
+
+% todo: palets in definecolor
+% todo: {\red xx} vs \red{xx}
+
+% \def\mptexcolor#1{"\dogetattributeid\s!color \somecolorattribute{#1} A"}
+%
+% \startMPpage
+% fill fullcircle scaled 10cm ;
+% fill fullcircle scaled 5cm withprescript \mptexcolor{red} withpostscript \mptexcolor{black} ;
+% fill fullcircle scaled 3cm ;
+% draw btex test etex withprescript \mptexcolor{blue} ;
+% \stopMPpage
+
+\unexpanded\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is
+ {\colo_helpers_set_model{#1}} % only for local usage
+
+\def\colo_helpers_set_model#1% direct
+ {\edef\currentcolormodel{#1}%
+ \clf_setcolormodel{\currentcolormodel}{\m_colo_weight_gray}} % sets attribute at lua end
+
+\colo_helpers_set_model\s!all
+
+\def\colo_helpers_set_current_model
+ {\ifconditional\c_colo_enabled
+ \ifconditional\c_colo_rgb_supported
+ \ifconditional\c_colo_cmyk_supported
+ \colo_helpers_set_model\s!all
+ \else
+ \colo_helpers_set_model\s!rgb
+ \fi
+ \else
+ \ifconditional\c_colo_cmyk_supported
+ \colo_helpers_set_model\s!cmyk
+ \else
+ \ifconditional\c_colo_convert_gray
+ \colo_helpers_set_model\s!gray
+ \else
+ \colo_helpers_set_model\s!none
+ \fi
+ \fi
+ \fi
+ \else
+ \ifconditional\c_colo_convert_gray
+ \colo_helpers_set_model\s!gray
+ \else
+ \colo_helpers_set_model\s!none
+ \fi
+ \fi}
+
+%D Currently in mkiv transparency is implemented independent of color. This costs a
+%D bit more processing time but gives the possibility to apply transparency
+%D independently in the future. Is this useful? If not we may as well combine them
+%D again in the future. By coupling we are downward compatible. When we decouple we
+%D need to do more tricky housekeeping (e.g. persist color independent
+%D transparencies when color bound ones are nil.
+
+% Since we couple definitions, we could stick to one test. Todo. Same for mpcolor.
+
+\def\v_colo_dummy_name{c_o_l_o_r}
+
+\letvalue{\??colorattribute \v_colo_dummy_name}\empty
+\letvalue{\??transparencyattribute\v_colo_dummy_name}\empty
+\letvalue{\??colorsetter \v_colo_dummy_name}\empty
+\letvalue{\??transparencysetter \v_colo_dummy_name}\empty
+
+\letvalue{\??colorsetter -}\empty % used?
+\letvalue{\??transparencysetter-}\empty % used?
+
+% new: expandable (see tbl)
+
+\def\colo_helpers_fast_activate
+ {\ifx\currentcolorprefix\empty
+ \expandafter\colo_helpers_fast_activate_nop
+ \else
+ \expandafter\colo_helpers_fast_activate_yes
+ \fi}
+
+\def\colo_helpers_fast_activate_yes#1%
+ {\ifcsname\??colorsetter\currentcolorprefix#1\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter\currentcolorprefix#1\endcsname
+ \orelse\ifcsname\??colorsetter#1\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter#1\endcsname
+ \fi}
+
+\def\colo_helpers_fast_activate_nop#1%
+ {\ifcsname\??colorsetter#1\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter#1\endcsname
+ \fi}
+
+\def\colo_helpers_activate_dummy
+ {\begincsname\??colorsetter \v_colo_dummy_name\endcsname
+ \begincsname\??transparencysetter\v_colo_dummy_name\endcsname}
+
+\let\dofastcoloractivation\colo_helpers_fast_activate
+
+% so far
+
+\def\colo_helpers_activate#1% two-step is not that much faster but less tracing
+ {\edef\currentcolorname{#1}%
+ \ifx\currentcolorprefix\empty
+ \expandafter\colo_helpers_activate_nop
+ \else
+ \expandafter\colo_helpers_activate_yes
+ \fi}
+
+\def\colo_helpers_activate_yes
+ {\ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter\currentcolorprefix\currentcolorname\endcsname
+ \orelse\ifcsname\??colorsetter\currentcolorname\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter\currentcolorname\endcsname
+ \fi}
+
+\def\colo_helpers_activate_nop
+ {\ifcsname\??colorsetter\currentcolorname\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter\currentcolorname\endcsname
+ \fi}
+
+\def\colo_helpers_activate_yes_only
+ {\ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??colorsetter\currentcolorname\endcsname
+ \lastnamedcs
+ \fi}
+
+\def\colo_helpers_activate_nop_only
+ {\ifcsname\??colorsetter\currentcolorname\endcsname
+ \lastnamedcs
+ \fi}
+
+\let\dousecolorparameter\colo_helpers_activate
+
+\unexpanded\def\dousecolorhashparameter#1#2%
+ {\ifcsname#1#2\endcsname
+ \expandafter\dousecolorparameter\csname#1#2\endcsname
+ \fi}
+
+\unexpanded\def\dousecurrentcolorparameter
+ {\let\currentcolorname\currentcolorparameter % maybe only when success
+ \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter\currentcolorprefix\currentcolorparameter\endcsname
+ \orelse\ifcsname\??colorsetter\currentcolorparameter\endcsname
+ \lastnamedcs
+ \begincsname\??transparencysetter\currentcolorparameter\endcsname
+ \fi}
+
+\let\dosetcolorattribute\dousecolorhashparameter % for a while
+
+\unexpanded\def\deactivatecolor % sort of public but a bad name
+ {\let\currentcolorname\s!black
+ \attribute\colorattribute\attributeunsetvalue
+ \attribute\transparencyattribute\attributeunsetvalue}
+
+% todo: check if color is overloading a non-color command
+
+% \let\colo_basics_synchronize\gobbleoneargument % used in mp interface
+% \let\colo_basics_inherit \gobbletwoarguments % used in mp interface
+
+\def\colo_basics_allocate#1%
+ {\expandafter\newcount\csname\??colornumber#1\endcsname
+ \clf_synccolorcount{#1}\c_syst_last_allocated_count}
+
+\def\colo_basics_synchronize#1%
+ {\ifcsname\??colornumber#1\endcsname\else
+ \colo_basics_allocate{#1}%
+ \fi
+ \clf_synccolor{#1}%
+ %\csname\??colornumber#1\endcsname\csname\??colorattribute#1\endcsname
+ \lastnamedcs\csname\??colorattribute#1\endcsname}
+
+\let\colo_basics_inherit\clf_synccolorclone
+
+\newcount\c_colo_protection
+
+\unexpanded\def\startprotectedcolors
+ {\advance\c_colo_protection\plusone}
+
+\unexpanded\def\stopprotectedcolors
+ {\advance\c_colo_protection\minusone}
+
+\def\colo_basics_define[#1][#2]%
+ {\edef\m_colo_old{#1}%
+ \edef\m_colo_new{#2}%
+ \ifx\m_colo_old\m_colo_new
+ % maybe a warning
+ \else
+ \clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
+ \colo_basics_synchronize{#1}%
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi
+ \fi}
+
+\def\colo_basics_define_global[#1][#2]%
+ {\edef\m_colo_old{#1}%
+ \edef\m_colo_new{#2}%
+ \ifx\m_colo_old\m_colo_new
+ % maybe a warning
+ \else
+ \clf_defineprocesscolorglobal{#1}{#2}\v_colo_freeze_state\relax
+ \colo_basics_synchronize{#1}%
+ \ifcase\c_colo_protection
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi
+ \fi}
+
+\let\colo_basics_define_named\colo_basics_define
+
+\def\dodefinefastcolor[#1][#2]% still not fast but ok (might change)
+ {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
+ \colo_basics_synchronize{#1}%
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_defined_and_activated#1%
+ {\clf_defineprocesscolordummy{#1}% we could pass dummy here too
+ \colo_basics_synchronize{\v_colo_dummy_name}%
+ \colo_helpers_activate_dummy}
+
+\def\colo_basics_define_process
+ {\ifthirdargument
+ \expandafter\colo_basics_define_process_yes
+ \else
+ \expandafter\colo_basics_define_process_nop
+ \fi}
+
+\def\colo_basics_define_process_yes[#1][#2][#3]%
+ {\clf_defineprocesscolorlocal{#1}{\processcolorcomponents{#2},#3}\v_colo_freeze_state\relax
+ \colo_basics_synchronize{#1}%
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_define_process_nop[#1][#2][#3]%
+ {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
+ \colo_basics_synchronize{#1}%
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+%D Spotcolors used setxvalue but that messes up currentcolor and probably no global
+%D is needed either but they are global at the lua end (true argument) so we keep
+%D that if only because spot colors often are a document wide property
+
+\def\colo_basics_define_spot[#1][#2][#3]%
+ {\clf_definespotcolorglobal{#1}{#2}{#3}%
+ \colo_basics_synchronize{#1}%
+ \ifcase\c_colo_protection
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_define_multitone[#1][#2][#3][#4]%
+ {\clf_definemultitonecolorglobal{#1}{#2}{#3}{#4}%
+ \colo_basics_synchronize{#1}%
+ \ifcase\c_colo_protection
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+%D Transparencies (only):
+
+\def\colo_basics_define_transpancy[#1][#2]%
+ {\clf_definetransparency{#1}{#2}}
+
+\def\colo_basics_define_transpancy_global[#1][#2]%
+ {\clf_definetransparencyglobal{#1}{#2}}
+
+% A goodie that replaces the startMPcolor hackery
+
+% \definecolor[red-t] [r=1,t=0.5,a=1]
+% \definecolor[green-t][g=1,t=0.5,a=1]
+%
+% \defineintermediatecolor[mycolora][0.5,red,green]
+% \defineintermediatecolor[mycolorb][0.5,red-t,green-t]
+%
+% \definecolor[mycolorc][.5(blue,red)]
+% \definecolor[mycolord][.5(blue)]
+% \definecolor[mycolord][-.5(blue,red)] % complement
+% \definecolor[mycolord][-(blue)] % complement
+%
+% \enabledirectives[colors.pgf]
+% \definecolor[mycolorx][magenta!50!yellow]
+%
+% \starttext
+% test {\mycolora OEPS} test
+% test {\mycolorb OEPS} test
+% test {\mycolorc OEPS} test
+% test {\mycolord OEPS} test
+% test {\mycolorx OEPS} test
+% \stoptext
+%
+% Beware: if we say:
+%
+% \definecolor[one][two]
+%
+% Only color one is actually defined and two is not seen at the \LUA\ end. This
+% means that this doesn't work:
+%
+% \definecolor[ColorA][red]
+% \definecolor[ColorB][.5(ColorA)]
+% \definecolor[ColorC][.5(ColorB,white)]
+%
+% But this does work:
+%
+% \definecolor[ColorA][1.0(red)]
+% \definecolor[ColorB][0.5(ColorA)]
+% \definecolor[ColorC][0.5(ColorB,white)]
+%
+% because the fractional definition results in a new definition.
+
+\unexpanded\def\defineintermediatecolor
+ {\dotripleempty\colo_basics_define_intermediate}
+
+\def\colo_basics_define_intermediate[#1][#2][#3]% \dotripleempty adds {} inside []
+ {\colo_basics_define_intermediate_indeed[#1][#2][#3]}
+
+\def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]%
+ {\clf_defineintermediatecolor % not global
+ {#1}%
+ {#2}%
+ \rawcolorattribute{#3} %
+ \rawcolorattribute{#4} %
+ \rawtransparencyattribute{#3} %
+ \rawtransparencyattribute{#4} %
+ {#5}%
+ \v_colo_freeze_state
+ \relax
+ \colo_basics_synchronize{#1}%
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
+
+%D Here is a more efficient helper for pgf:
+%D
+%D \starttyping
+%D \startluacode
+%D function commands.pgfxcolorspec(ca) -- {}{}{colorspace}{list}
+%D local cv = attributes.colors.values[ca]
+%D if cv then
+%D local model = cv[1]
+%D if model == 2 then
+%D context("{}{}{gray}{%1.3f}",cv[2])
+%D elseif model == 3 then
+%D context("{}{}{rgb}{%1.3f,%1.3f,%1.3f}",cv[3],cv[4],cv[5])
+%D elseif model == 4 then
+%D context("{}{}{cmyk}{%1.3f,%1.3f,%1.3f,%1.3f}",cv[6],cv[7],cv[8],cv[9])
+%D else
+%D context("{}{}{gray}{%1.3f}",cv[2])
+%D end
+%D else
+%D context("{}{}{gray}{0}")
+%D end
+%D end
+%D \stopluacode
+%D
+%D \def\pgfutil@registercolor#1%
+%D {\setevalue{\string\color@#1}{\noexpand\xcolor@\ctxcommand{pgfxcolorspec(\thecolorattribute{#1})}}}
+%D
+%D \definecolor [darkblue] [r=0,g=0,b=0.5]
+%D
+%D \starttikzpicture
+%D \fill [blue] (0,0) circle(1);
+%D \fill [darkblue] (0,0) circle(1);
+%D \stoptikzpicture
+%D \stoptyping
+%D
+%D \stopmode
+
+\def\pgf@context@registercolor#1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\zerocount\thecolorattribute{#1}}}
+\def\pgf@context@registergray #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plustwo \thecolorattribute{#1}}}
+\def\pgf@context@registerrgb #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plusthree\thecolorattribute{#1}}}
+\def\pgf@context@registercmyk #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plusfour \thecolorattribute{#1}}}
+
+%D \starttyping
+%D \ifdefined\pgf@context@registercolor
+%D \let\pgfutil@registercolor\pgf@context@registercolor
+%D \fi
+%D \stoptyping
+
+%D \macros
+%D {doifcolorelse, doifcolor}
+%D
+%D Switching to a color is done by means of the following command. Later on we will
+%D explain the use of palets. We define ourselves a color conditional first.
+
+\def\doifelsecolor#1%
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \expandafter\firstoftwoarguments
+ \orelse\ifcsname\??colorattribute#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifcolorelse\doifelsecolor
+
+\def\doifcolor#1%
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \expandafter\firstofoneargument
+ \orelse\ifcsname\??colorattribute#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D \macros
+%D {startregistercolor,stopregistercolor,permitcolormode}
+%D
+%D If you only want to register a color, the switch \type {\ifpermitcolormode} can
+%D be used. That way the nested colors know where to go back to.
+%D
+%D We use these macros for implementing text colors (actually, the first application
+%D was in foreground colors).
+%D
+%D \starttyping
+%D \starttextcolor[red]
+%D \dorecurse{10}{\input tufte \color[green]{oeps} \par}
+%D \stoptextcolor
+%D \stoptyping
+%D
+%D This is more efficient than the alternative:
+%D
+%D \starttyping
+%D \setupbackgrounds[text][foregroundcolor=red]
+%D \startregistercolor[red]
+%D \dorecurse{10}{\input tufte \color[green]{oeps} \par}
+%D \stopregistercolor
+%D \stoptyping
+
+\let\maintextcolor \empty
+\def\defaulttextcolor {black}
+\def\s!themaintextcolor{themaintextcolor}
+
+\unexpanded\def\inheritmaintextcolor
+ {\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi}
+
+\unexpanded\def\onlyinheritmaintextcolor
+ {\ifx\maintextcolor\empty
+ \deactivatecolor
+ \else
+ \colo_helpers_activate\maintextcolor
+ \fi}
+
+\appendtoks
+ \deactivatecolor % public?
+ \inheritmaintextcolor
+\to \everybeforeoutput
+
+\def\colo_helpers_switch_to_maintextcolor#1%
+ {\let\maintextcolor\s!themaintextcolor
+ \definecolor[\maintextcolor][#1]% can be fast one
+ \colo_helpers_activate\maintextcolor
+ \clf_registermaintextcolor\thecolorattribute\maintextcolor\relax}
+
+\unexpanded\def\starttextcolor[#1]%
+ {\doifsomething{#1}
+ {\colo_helpers_switch_to_maintextcolor{#1}}}
+
+\let\stoptextcolor\relax
+
+\let\p_colo_textcolor\empty
+
+\def\colo_helpers_initialize_maintextcolor
+ {\edef\p_colo_textcolor{\directcolorsparameter\c!textcolor}%
+ \ifx\p_colo_textcolor\empty
+ \colo_helpers_switch_to_maintextcolor\defaulttextcolor
+ \else
+ \colo_helpers_switch_to_maintextcolor\p_colo_textcolor
+ \fi}
+
+\appendtoks \colo_helpers_initialize_maintextcolor \to \everyjob
+\appendtoks \colo_helpers_initialize_maintextcolor \to \everysetupcolors
+
+\letvalue{\??colorsetter }\empty \letvalue{\??colorattribute }\!!zerocount
+\letvalue{\??transparencysetter}\empty \letvalue{\??transparencyattribute}\!!zerocount
+
+\def\colo_helpers_inherited_direct_cs#1{\ifcsname\??colorsetter #1\endcsname\lastnamedcs\fi}
+\def\colo_helpers_inherited_direct_ca#1{\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi}
+\def\colo_helpers_inherited_direct_ts#1{\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\fi}
+\def\colo_helpers_inherited_direct_ta#1{\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi}
+
+% %def\colo_helpers_inherited_palet_cs#1#2{\csname\??colorsetter \ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+% %def\colo_helpers_inherited_palet_ca#1#2{\csname\??colorattribute \ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+% %def\colo_helpers_inherited_palet_ts#1#2{\csname\??transparencysetter \ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+% %def\colo_helpers_inherited_palet_ta#1#2{\csname\??transparencyattribute\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+%
+% \def\colo_helpers_inherited_palet_cs#1#2{\ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\lastnamedcs\fi}
+% \def\colo_helpers_inherited_palet_ca#1#2{\ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi}
+% \def\colo_helpers_inherited_palet_ts#1#2{\ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\lastnamedcs}
+% \def\colo_helpers_inherited_palet_ta#1#2{\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi}
+
+\let\colo_helpers_set_value\setvalue
+
+\appendtoks
+ \ifconditional\c_colo_expanded
+ \let\colo_helpers_set_value\setevalue
+ \else
+ \let\colo_helpers_set_value\setvalue
+ \fi
+\to \everysetupcolors
+
+\def\colo_palets_define_set#1#2#3%
+ {\ifcondition\validassignment{#3}% \definepalet[test][xx={y=.4}]
+ \expandafter\colo_palets_define_assign
+ \orelse\ifcsname\??colorsetter#3\endcsname
+ % \definepalet[test][xx=green]
+ \expandafter\colo_palets_define_inherit
+ \else
+ % not entered when making format
+ \expandafter\colo_palets_define_undefine
+ \fi
+ {#1}{#2}{#3}}
+
+\def\colo_palets_define_inherit#1#2#3%
+ {\colo_basics_inherit{#1:#2}{#3}%
+ \colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_direct_cs{#3}}%
+ \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_direct_ca{#3}}%
+ \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_direct_ts{#3}}%
+ \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_direct_ta{#3}}}
+
+\def\colo_palets_define_undefine#1#2#3%
+ {\localundefine{\??colorsetter #1:#2}%
+ \localundefine{\??colorattribute #1:#2}%
+ \localundefine{\??transparencysetter #1:#2}%
+ \localundefine{\??transparencyattribute#1:#2}}
+
+\def\colo_palets_define_assign#1#2#3%
+ {\definecolor[\??colorpalet#1:#2][#3]%
+ \colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_direct_cs{\??colorpalet#1:#2}}%
+ \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_direct_ca{\??colorpalet#1:#2}}%
+ \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_direct_ts{\??colorpalet#1:#2}}%
+ \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_direct_ta{\??colorpalet#1:#2}}}
+
+\setvalue{\??colorattribute currentcolor}{\the\attribute\colorattribute} % for mpcolor
+\setvalue{\??transparencyattribute currentcolor}{\the\attribute\transparencyattribute} % for mpcolor
+
+%def\colo_helpers_inherited_current_ca#1{\csname\??colorattribute \ifcsname\??colorattribute \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute #1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_cs#1{\csname\??colorsetter \ifcsname\??colorsetter \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorsetter #1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_ts#1{\csname\??transparencysetter \ifcsname\??transparencysetter \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencysetter #1\endcsname#1\fi\fi\endcsname}
+
+\def\colo_helpers_inherited_current_ca#1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi\fi}
+\def\colo_helpers_inherited_current_cs#1{\ifcsname\??colorsetter \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorsetter #1\endcsname\lastnamedcs\else\fi\fi}
+\def\colo_helpers_inherited_current_ta#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi\fi}
+\def\colo_helpers_inherited_current_ts#1{\ifcsname\??transparencysetter \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\else\fi\fi}
+
+%D Low level defs:
+
+\unexpanded\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\attribute\colorattribute #2 }}
+\unexpanded\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\attribute\colorattribute #2 }} % was not g
+\unexpanded\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\attribute\transparencyattribute#2 }}
+\unexpanded\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\attribute\transparencyattribute#2 }}
+
+\unexpanded\def\colordefflc#1#2{\setvalue {\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
+\unexpanded\def\colordeffgc#1#2{\setgvalue{\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
+\unexpanded\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
+\unexpanded\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
+
+\unexpanded\def\colordefrlc #1{\localundefine {\??colorattribute #1}\localundefine {\??colorsetter #1}}
+\unexpanded\def\colordefrgc #1{\globalundefine{\??colorattribute #1}\globalundefine{\??colorsetter #1}}
+\unexpanded\def\colordefrlt #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}}
+\unexpanded\def\colordefrgt #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}}
+
+%D \macros
+%D {colorvalue, grayvalue}
+%D
+%D We can typeset the color components using \type {\colorvalue} and \type
+%D {\grayvalue}. The commands:
+%D
+%D \startbuffer
+%D color value of SomeKindOfRed: \colorvalue{SomeKindOfRed} \crlf
+%D gray value of SomeKindOfRed: \grayvalue{SomeKindOfRed}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D show us:
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+
+\let\currentcolorname\s!black % todo
+\let\outercolorname \s!black % todo
+
+\let\colorformatseparator\space
+
+\def\MPcolor#1%
+ {\clf_mpcolor
+ \attribute\colormodelattribute
+ \colo_helpers_inherited_current_ca{#1} %
+ \colo_helpers_inherited_current_ta{#1} }
+
+\def\MPcoloronly#1%
+ {\clf_mpcolor
+ \attribute\colormodelattribute
+ \colo_helpers_inherited_current_ca{#1} %
+ \zerocount}
+
+\def\MPtransparency#1%
+ {\clf_mpcolor
+ \zerocount
+ \zerocount
+ \colo_helpers_inherited_current_ta{#1} }
+
+\def\MPoptions#1%
+ {\clf_mpoptions
+ \attribute\colormodelattribute
+ \colo_helpers_inherited_current_ca{#1} %
+ \colo_helpers_inherited_current_ta{#1} }
+
+\def\thecolormodelattribute {\the\attribute\colormodelattribute}
+
+%def\thecolorattribute #1{\number\csname\??colorattribute \ifcsname\??colorattribute \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute #1\endcsname#1\fi\fi\endcsname}
+%def\thetransparencyattribute#1{\number\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+
+\def\rawcolorattribute #1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi}
+\def\rawtransparencyattribute#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi}
+
+\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi}
+\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi}
+\def\internalspotcolorname #1{\clf_spotcolorname \thecolorattribute{#1} }
+\def\internalspotcolorparent #1{\clf_spotcolorparent\thecolorattribute{#1} }
+\def\internalspotcolorsize #1{\clf_spotcolorvalue \thecolorattribute{#1} }
+
+\def\colorcomponents #1{\clf_colorcomponents \thecolorattribute {#1} }
+\def\transparencycomponents #1{\clf_transparencycomponents\thetransparencyattribute{#1} }
+\def\processcolorcomponents #1{\clf_processcolorcomponents\thecolorattribute {#1} }
+
+\def\colorvalue #1{\clf_formatcolor\thecolorattribute{#1}{\colorformatseparator}}
+\def\grayvalue #1{\clf_formatgray \thecolorattribute{#1}{\colorformatseparator}}
+
+\def\doifelseblack #1{\clf_doifelseblack\thecolorattribute{#1} }
+\def\doifelsedrawingblack {\clf_doifelsedrawingblack}
+
+\let\doifblackelse \doifelseblack
+\let\doifdrawingblackelse \doifelsedrawingblack
+
+\let\doifblackelse \doifelseblack
+\let\doifdrawingblackelse\doifelsedrawingblack
+
+%D \macros
+%D {forcecolorhack}
+%D
+%D We can out this in front of (for instance) a special and so force color to be
+%D applied (only glyphs, rules and leaders are handled).
+%D
+%D \startbuffer
+%D \framed
+%D [background=color,backgroundcolor=yellow,framecolor=red,corner=round]
+%D {test}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% ignores in attribute handler
+%
+% \def\forcecolorhack{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
+
+% \normal added else fails in metafun manual (leaders do a hard scan)
+
+\unexpanded\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed !
+
+%D We default to the colors defined in \type {colo-imp-rgb} and
+%D support both \RGB\ and \CMYK\ output. Transparencies are defined
+%D here:
+
+\definecolor[black][s=0]
+\definecolor[white][s=1]
+
+\definetransparency [none] [0]
+\definetransparency [normal] [1]
+\definetransparency [multiply] [2]
+\definetransparency [screen] [3]
+\definetransparency [overlay] [4]
+\definetransparency [softlight] [5]
+\definetransparency [hardlight] [6]
+\definetransparency [colordodge] [7]
+\definetransparency [colorburn] [8]
+\definetransparency [darken] [9]
+\definetransparency [lighten] [10]
+\definetransparency [difference] [11]
+\definetransparency [exclusion] [12]
+\definetransparency [hue] [13]
+\definetransparency [saturation] [14]
+\definetransparency [color] [15]
+\definetransparency [luminosity] [16]
+
+%D Some common ones:
+
+\definecolor[trace:0][s=.4]
+\definecolor[trace:1][r=.6]
+\definecolor[trace:2][g=.6]
+\definecolor[trace:3][b=.6]
+\definecolor[trace:4][r=.6,g=.6]
+\definecolor[trace:5][r=.6,b=.6]
+\definecolor[trace:6][g=.6,b=.6]
+\definecolor[trace:7][r=.8,g=.4]
+\definecolor[trace:8][r=.8,b=.4]
+\definecolor[trace:9][g=.4,b=.8]
+
+\definecolor[trace:w][s=1]
+\definecolor[trace:r][r=.75,t=.5,a=1]
+\definecolor[trace:g][g=.75,t=.5,a=1]
+\definecolor[trace:b][b=.75,t=.5,a=1]
+%definecolor[trace:c][c=.75,t=.5,a=1]
+\definecolor[trace:c][g=.75,b=.75,t=.5,a=1]
+%definecolor[trace:m][m=.75,t=.5,a=1]
+\definecolor[trace:m][r=.75,b=.75,t=.5,a=1]
+%definecolor[trace:y][y=.75,t=.5,a=1]
+\definecolor[trace:y][r=.75,g=.75,t=.5,a=1]
+\definecolor[trace:s][s=.75,t=.5,a=1]
+\definecolor[trace:d][s=.25,t=.5,a=1]
+\definecolor[trace:o][r=1,g=.6,b=.1,t=.5,a=1]
+
+\definecolor[trace:dw][s=1]
+\definecolor[trace:dr][r=.75,t=.75,a=1]
+\definecolor[trace:dg][g=.75,t=.75,a=1]
+\definecolor[trace:db][b=.75,t=.75,a=1]
+%definecolor[trace:dc][c=.75,t=.75,a=1]
+\definecolor[trace:dc][g=.75,b=.75,t=.75,a=1]
+%definecolor[trace:dm][m=.75,t=.75,a=1]
+\definecolor[trace:dm][r=.75,b=.75,t=.75,a=1]
+%definecolor[trace:dy][y=.75,t=.75,a=1]
+\definecolor[trace:y][r=.75,g=.75,t=.75,a=1]
+\definecolor[trace:ds][s=.75,t=.75,a=1]
+\definecolor[trace:dd][s=.25,t=.75,a=1]
+\definecolor[trace:do][r=1,g=.6,b=.1,t=.75,a=1]
+
+\setupcolors
+ [\c!state=\v!stop, % color will be enabled later on
+ \c!conversion=\v!yes,
+ \c!rgb=\v!yes,
+ \c!cmyk=\v!yes,
+ \c!spot=\v!yes,
+ \c!pagecolormodel=\v!none,
+ \c!expansion=\v!no,
+ \c!textcolor=,
+ \c!factor=\v!yes]
+
+\setupcolor
+ [\v!rgb]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/cont-cs.mkxl b/tex/context/base/mkiv/cont-cs.mkxl
new file mode 100644
index 000000000..8e5ae567c
--- /dev/null
+++ b/tex/context/base/mkiv/cont-cs.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-cs,
+%D version=1998.12.02,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Czech Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {czech}
+\def\defaultlanguagetag{cs}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-de.mkxl b/tex/context/base/mkiv/cont-de.mkxl
new file mode 100644
index 000000000..579cc88c3
--- /dev/null
+++ b/tex/context/base/mkiv/cont-de.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-de,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ German Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {german}
+\def\defaultlanguagetag{de}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-en.mkxl b/tex/context/base/mkiv/cont-en.mkxl
new file mode 100644
index 000000000..bfb17ffb3
--- /dev/null
+++ b/tex/context/base/mkiv/cont-en.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-en,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ English Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {english}
+\def\defaultlanguagetag{en}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-fr.mkxl b/tex/context/base/mkiv/cont-fr.mkxl
new file mode 100644
index 000000000..bedae536b
--- /dev/null
+++ b/tex/context/base/mkiv/cont-fr.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-de,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ French Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {french}
+\def\defaultlanguagetag{fr}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-gb.mkxl b/tex/context/base/mkiv/cont-gb.mkxl
new file mode 100644
index 000000000..464b237da
--- /dev/null
+++ b/tex/context/base/mkiv/cont-gb.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-uk,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ English Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {english}
+\def\defaultlanguagetag{gb}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-it.mkxl b/tex/context/base/mkiv/cont-it.mkxl
new file mode 100644
index 000000000..1702a872f
--- /dev/null
+++ b/tex/context/base/mkiv/cont-it.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-it,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Italian Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {italian}
+\def\defaultlanguagetag{it}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 102438f7a..08abe123a 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{2019.07.24 11:17}
+\newcontextversion{2019.07.31 18:05}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/cont-nl.mkxl b/tex/context/base/mkiv/cont-nl.mkxl
new file mode 100644
index 000000000..1f00e7e89
--- /dev/null
+++ b/tex/context/base/mkiv/cont-nl.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-nl,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Dutch Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {dutch}
+\def\defaultlanguagetag{nl}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-pe.mkxl b/tex/context/base/mkiv/cont-pe.mkxl
new file mode 100644
index 000000000..82bf73721
--- /dev/null
+++ b/tex/context/base/mkiv/cont-pe.mkxl
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=cont-en,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ English Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {persian}
+\def\messageinterface {english}
+\def\defaultlanguagetag{pe}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-ro.mkxl b/tex/context/base/mkiv/cont-ro.mkxl
new file mode 100644
index 000000000..6d636c7dc
--- /dev/null
+++ b/tex/context/base/mkiv/cont-ro.mkxl
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-ro,
+%D version=2000.01.09,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Romanian Format Generation,
+%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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {romanian}
+\def\defaultlanguagetag{ro}
+
+\input context.mkxl
+
+\endinput
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index fe13d5930..497bfdc08 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{2019.07.24 11:17}
+\edef\contextversion{2019.07.31 18:05}
\edef\contextkind {beta}
%D Kind of special:
@@ -137,8 +137,6 @@
\loadmkvifile{file-res}
\loadmkvifile{file-lib}
-\loadmarkfile{core-lmt} % lmtx
-
%D This needs more checking for clashes:
%D
%D \starttyping
@@ -188,7 +186,6 @@
\loadmarkfile{back-ini}
\loadmarkfile{back-res}
\loadmarkfile{back-trf}
-\loadmarkfile{back-out}
\loadmarkfile{attr-col}
\loadmarkfile{attr-lay}
@@ -586,8 +583,6 @@
\loadmarkfile{back-exp}
\loadmarkfile{back-pdf}
-\loadmarkfile{back-mps}
-\loadmarkfile{back-lua}
\loadmarkfile{mlib-pdf}
\loadmarkfile{mlib-pps}
@@ -604,7 +599,9 @@
\loadmarkfile{cont-run} % the main runner (used in cont-yes.mkiv)
-\loadmarkfile{driv-shp}
+\appendtoks
+ \setupoutput[pdf]
+\to \everyjob
\setupcurrentlanguage[\defaultlanguagetag]
diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl
new file mode 100644
index 000000000..f3373a1f7
--- /dev/null
+++ b/tex/context/base/mkiv/context.mkxl
@@ -0,0 +1,625 @@
+%D \module
+%D [ file=context,
+%D version=2019.07.24, % 2008.28.10, % 1995.10.10,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Format Generation,
+%D author=Hans Hagen, % ɦɑns ɦɑˈχən
+%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.
+
+% http://build.contextgarden.net/waterfall?tag=c/lua(meta)tex
+
+%D Welcome to context, pronounced as kontekst (rather dutch) and not as conτεχt.
+
+\catcode`\{=1 \catcode`\}=2 \catcode`\#=6
+
+%D From the next string (which is set by the script that assembles the distribution)
+%D later on we will calculate a number that can be used by use modules to identify
+%D the feature level. Starting with version 2004.8.30 the low level interface is
+%D english. Watch out and adapt your styles an modules.
+
+% \everypar{\writestatus{!!!!}{some spurious input in line \the\inputlineno}\wait}
+
+%D The order of loading will change when all modules have been cleaned up and the
+%D dependencies are more consistent. Beware, the version number has to match \type
+%D {YYYY.MM.DD HH:MM} format.
+
+\edef\contextformat {\jobname}
+\edef\contextversion{2019.07.31 18:05}
+\edef\contextkind {beta}
+
+%D Kind of special:
+
+\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax
+
+%D For those who want to use this:
+
+\let\fmtname \contextformat
+\let\fmtversion\contextversion
+
+%D Loading:
+
+\edef\mksuffix {mkiv}
+\edef\contextmark{MKIV}
+
+\ifx\normalinput\undefined \let\normalinput\input \fi
+
+\def\loadmarkfile#1{\normalinput{#1.\mksuffix}}
+\def\loadmkivfile#1{\normalinput{#1.mkiv}}
+\def\loadmkvifile#1{\normalinput{#1.mkvi}}
+\def\loadmkxlfile#1{\normalinput{#1.mkxl}}
+\def\loadmklxfile#1{\normalinput{#1.mklx}}
+
+% \def\loadmkxlfile#1{\normalinput{#1.mkiv}}
+% \def\loadmklxfile#1{\normalinput{#1.mkvi}}
+
+%D First we load the system modules. These implement a lot of manipulation macros.
+%D We start with setting up some basic \TEX\ machinery.
+
+\loadmkxlfile{syst-ini}
+
+%D We just quit if new functionality is expected.
+
+\ifnum\luatexversion<200 % also change message
+ \writestatus{!!!!}{Your luametatex binary is too old, you need at least version 2.00!}
+ \expandafter\end
+\fi
+
+%D Some checking (more primitives are now defined):
+
+\ifdefined\defaultinterface \else \def\defaultinterface {english} \fi
+%ifdefined\messageinterface \else \let\messageinterface \defaultinterface \fi
+\ifdefined\defaultlanguagetag \else \def\defaultlanguagetag{en} \fi
+
+%D There is only this way to pass the version info to \LUA\ (currently). Hm, we could
+%D now put it into the environment.
+
+\newtoks\contextversiontoks \contextversiontoks\expandafter{\contextversion}
+\newtoks\contextkindtoks \contextkindtoks \expandafter{\contextkind}
+
+% \normaleverypar{\wait} % uncomment for test of funny injections
+
+%D Now the more fundamental code gets defined.
+
+\loadmarkfile{norm-ctx}
+\loadmarkfile{syst-pln}
+\loadmarkfile{syst-mes}
+
+\loadmarkfile{luat-cod}
+\loadmarkfile{luat-bas}
+\loadmarkfile{luat-lib}
+\loadmarkfile{luat-soc}
+
+\loadmarkfile{catc-ini}
+\loadmarkfile{catc-act}
+\loadmarkfile{catc-def}
+\loadmarkfile{catc-ctx}
+\loadmarkfile{catc-sym}
+
+\loadmarkfile{toks-ini}
+\loadmarkfile{cldf-ini}
+
+% \tracecatcodetables
+
+%D From here on we have \unexpanded being \normalprotected, as we already had
+%D \type {\unexpanded} long before etex came around.
+
+\loadmarkfile{luat-ini}
+\loadmarkfile{toks-scn}
+
+\loadmkxlfile{syst-aux} % LMTX
+\loadmarkfile{syst-lua}
+\loadmarkfile{syst-con}
+
+\loadmarkfile{syst-fnt}
+\loadmarkfile{syst-rtp}
+
+\loadmarkfile{luat-usr}
+
+\loadmkvifile{file-ini}
+\loadmkvifile{file-res}
+\loadmkvifile{file-lib}
+
+\loadmkxlfile{core-lmt} % LMTX
+
+%D This needs more checking for clashes:
+%D
+%D \starttyping
+%D \doifelsefileexists{l-macro-imp-codes.lua}{\registerctxluafile{l-macro-imp-codes}{}}{}
+%D \stoptyping
+
+\loadmarkfile{supp-dir}
+
+\loadmarkfile{char-utf} % generic code (i.e. not much tex) ... could become unic-ini
+\loadmarkfile{char-ini} % tex / context specific
+\loadmarkfile{char-act} % even more specific
+
+\loadmarkfile{mult-ini}
+\loadmarkfile{mult-sys}
+\loadmkxlfile{mult-aux} % LMTX
+\loadmarkfile{mult-def}
+\loadmarkfile{mult-chk}
+\loadmkvifile{mult-dim}
+
+\loadmarkfile{cldf-int} % interface
+
+\loadmarkfile{trac-ctx} % maybe move up
+
+% \loadmarkfile{luat-ini}
+
+\loadmarkfile{toks-tra}
+\loadmarkfile{toks-aux}
+%loadmarkfile{toks-map} % obsolete, never used
+
+\loadmarkfile{attr-ini}
+
+\loadmarkfile{core-ini}
+\loadmarkfile{core-env}
+
+\loadmarkfile{layo-ini}
+
+\loadmarkfile{node-ini}
+
+\loadmarkfile{cldf-bas} % basics / depends on nodes
+
+\loadmkivfile{node-fin}
+\loadmarkfile{node-mig}
+%loadmarkfile{node-pag}
+
+\loadmkxlfile{driv-ini} % LMTX
+
+\loadmkxlfile{back-ini}
+\loadmarkfile{back-res}
+\loadmarkfile{back-trf}
+\loadmkxlfile{back-out}
+
+\loadmarkfile{attr-col}
+\loadmarkfile{attr-lay}
+\loadmarkfile{attr-neg}
+\loadmarkfile{attr-eff}
+\loadmarkfile{attr-mkr}
+
+\loadmarkfile{trac-tex}
+\loadmarkfile{trac-deb} % will move up
+
+%loadmarkfile{blob-ini} % not to be used, we only use a helper
+
+\loadmkxlfile{supp-box} % LMTX
+
+\loadmarkfile{supp-ran}
+\loadmarkfile{supp-mat}
+
+\loadmarkfile{core-uti}
+\loadmkvifile{file-job}
+
+\loadmarkfile{anch-pos}
+
+\loadmarkfile{typo-ini}
+\loadmarkfile{typo-lin}
+\loadmarkfile{typo-bld} % par builders
+
+\loadmarkfile{typo-inj}
+
+\loadmkvifile{file-syn}
+\loadmkvifile{file-mod}
+
+\loadmarkfile{core-sys}
+\loadmarkfile{core-con}
+
+\loadmarkfile{cont-fil}
+
+\loadmarkfile{regi-ini}
+\loadmarkfile{enco-ini}
+\loadmarkfile{hand-ini}
+
+\loadmkxlfile{lang-ini} % LMTX
+\loadmarkfile{lang-hyp} % also loads dis
+\loadmkxlfile{lang-lab} % LMTX
+
+\loadmarkfile{unic-ini}
+
+% \loadmarkfile{core-uti}
+\loadmarkfile{core-two}
+\loadmarkfile{core-dat}
+
+\loadmkxlfile{colo-ini} % LMTX
+\loadmarkfile{colo-grp} % optional
+\loadmarkfile{colo-ext}
+
+\loadmarkfile{node-bck} % overloads anch-pgr (experimental and undocumented)
+
+\loadmarkfile{pack-cut}
+
+\loadmarkfile{lang-mis}
+\loadmarkfile{lang-url}
+\loadmarkfile{lang-def}
+
+% \loadmkvifile{file-job} % why so late?
+
+\loadmarkfile{symb-ini} % brrr depends on fonts
+
+\loadmarkfile{sort-ini}
+
+\loadmkvifile{pack-mis}
+\loadmkxlfile{pack-rul} % LMTX
+\loadmarkfile{pack-mrl}
+\loadmkvifile{pack-bck}
+\loadmarkfile{pack-fen}
+
+\loadmarkfile{lxml-ini}
+\loadmarkfile{lxml-sor}
+
+\loadmkvifile{typo-prc}
+
+% \loadmarkfile{anch-pos}
+
+\loadmkvifile{strc-ini}
+\loadmarkfile{strc-tag}
+\loadmarkfile{strc-doc}
+\loadmarkfile{strc-num}
+\loadmarkfile{strc-mar}
+\loadmarkfile{strc-sbe}
+\loadmkvifile{strc-lst}
+\loadmarkfile{strc-sec}
+\loadmarkfile{strc-pag} % hm, depends on core-num
+\loadmarkfile{strc-ren}
+\loadmarkfile{strc-xml}
+\loadmarkfile{strc-def} % might happen later
+\loadmkvifile{strc-ref}
+%loadmarkfile{strc-reg}
+\loadmkvifile{strc-lev} % experiment
+
+\loadmarkfile{spac-hor}
+\loadmarkfile{spac-ali}
+\loadmarkfile{spac-flr}
+\loadmkxlfile{spac-ver} % LMTX beware, hooks into strc-sec
+\loadmarkfile{spac-lin}
+\loadmarkfile{spac-pag}
+\loadmarkfile{spac-par}
+\loadmarkfile{spac-def}
+\loadmkvifile{spac-prf}
+\loadmarkfile{spac-grd}
+
+%loadmarkfile{anch-pos}
+
+\loadmkvifile{scrn-ini}
+\loadmkvifile{scrn-ref}
+
+\loadmarkfile{pack-obj}
+
+\loadmklxfile{strc-itm} % LMTX
+
+\loadmkvifile{strc-con}
+\loadmkvifile{strc-des}
+\loadmkvifile{strc-enu}
+
+\loadmarkfile{strc-ind}
+\loadmarkfile{strc-lab}
+\loadmarkfile{strc-syn}
+
+% \loadmarkfile{core-sys}
+
+\loadmarkfile{page-var}
+\loadmkvifile{page-otr}
+\loadmarkfile{page-ini}
+\loadmarkfile{page-ins}
+\loadmarkfile{page-fac}
+\loadmarkfile{page-brk}
+\loadmarkfile{page-col}
+\loadmarkfile{page-inf}
+\loadmarkfile{page-flt}
+\loadmarkfile{page-bck}
+\loadmarkfile{page-not}
+\loadmarkfile{page-one}
+\loadmarkfile{page-lay}
+\loadmkvifile{page-box}
+\loadmkvifile{page-txt}
+\loadmarkfile{page-sid} % when
+
+\loadmkvifile{strc-flt}
+
+\loadmarkfile{page-pst}
+\loadmkvifile{page-mbk}
+%loadmarkfile{page-mul} % \usecolumns[old-multicolumns]
+\loadmarkfile{page-mix}
+\loadmarkfile{page-smp}
+%loadmarkfile{page-set} % \usecolumns[old-columnsets]
+\loadmarkfile{page-cst}
+\loadmarkfile{page-pcl} % new
+\loadmarkfile{pack-lyr}
+\loadmarkfile{pack-pos}
+\loadmkvifile{page-mak}
+
+\loadmarkfile{strc-reg} % uses mixed columns
+
+\loadmkvifile{page-lin}
+\loadmarkfile{page-par}
+\loadmarkfile{typo-pag}
+\loadmarkfile{typo-mar}
+\loadmarkfile{typo-itm}
+
+\loadmarkfile{buff-ini}
+\loadmkxlfile{buff-ver} % LMTX
+\loadmkvifile{buff-par}
+
+\loadmarkfile{buff-imp-tex} % optional as also runtime if not loaded
+\loadmarkfile{buff-imp-mp} % optional as also runtime if not loaded
+\loadmarkfile{buff-imp-lua} % optional as also runtime if not loaded
+\loadmarkfile{buff-imp-xml} % optional as also runtime if not loaded
+
+\loadmarkfile{buff-imp-parsed-xml} % optional
+%loadmarkfile{buff-imp-parsed-lua} % optional
+
+\loadmarkfile{strc-blk}
+
+\loadmarkfile{page-imp}
+\loadmkvifile{page-sel} % optional
+\loadmkvifile{page-inj} % optional
+
+\loadmkvifile{scrn-pag}
+\loadmkvifile{scrn-wid}
+\loadmkvifile{scrn-but}
+\loadmkvifile{scrn-bar}
+
+\loadmarkfile{page-com} % optional (after scrn-pag)
+
+\loadmarkfile{strc-bkm} % bookmarks
+
+\loadmarkfile{java-ini}
+
+\loadmkvifile{scrn-fld}
+\loadmkvifile{scrn-hlp}
+
+\loadmarkfile{char-enc} % will move up
+
+\loadmkvifile{font-lib} % way too late but after language
+\loadmklxfile{font-fil} % LMTX
+\loadmkvifile{font-var}
+\loadmkvifile{font-fea}
+\loadmklxfile{font-mat} % LMTX
+\loadmklxfile{font-ini} % LMTX
+\loadmklxfile{font-sym} % LMTX
+\loadmklxfile{font-sty} % LMTX
+\loadmkvifile{font-set}
+\loadmklxfile{font-emp} % LMTX
+\loadmarkfile{font-pre}
+\loadmarkfile{font-unk}
+\loadmarkfile{font-tra}
+\loadmarkfile{font-chk}
+\loadmarkfile{font-uni}
+\loadmkvifile{font-col}
+\loadmkvifile{font-gds}
+\loadmkvifile{font-aux}
+\loadmkvifile{font-sel}
+
+\loadmarkfile{typo-tal}
+\loadmarkfile{typo-par} % par builders (uses fonts)
+
+\loadmarkfile{tabl-com}
+\loadmarkfile{tabl-pln}
+
+\loadmarkfile{tabl-tab} % thrd-tab stripped and merged
+
+\loadmkxlfile{tabl-tbl} % LMTX
+\loadmkxlfile{tabl-ntb} % LMTX
+\loadmarkfile{tabl-nte}
+\loadmarkfile{tabl-ltb}
+\loadmarkfile{tabl-frm}
+\loadmarkfile{tabl-tsp}
+\loadmkvifile{tabl-xtb}
+\loadmarkfile{tabl-mis}
+
+\loadmarkfile{typo-lan}
+
+\loadmarkfile{lxml-css}
+
+\loadmarkfile{spac-chr} % depends on fonts
+
+\loadmarkfile{blob-ini} % not to be used, we only use a helper
+
+\loadmarkfile{trac-vis}
+\loadmarkfile{trac-jus}
+
+\loadmarkfile{typo-cln}
+\loadmarkfile{typo-wrp}
+\loadmarkfile{typo-spa}
+\loadmarkfile{typo-krn}
+\loadmkvifile{typo-itc}
+\loadmarkfile{typo-dir}
+\loadmarkfile{typo-brk}
+\loadmarkfile{typo-cap}
+\loadmarkfile{typo-dig}
+\loadmarkfile{typo-rep}
+\loadmkvifile{typo-txt}
+\loadmarkfile{typo-drp}
+\loadmarkfile{typo-fln}
+\loadmarkfile{typo-sus}
+\loadmarkfile{typo-lig}
+\loadmarkfile{typo-chr}
+\loadmarkfile{typo-rub}
+\loadmkivfile{typo-fkr}
+\loadmkivfile{typo-pnc}
+
+\loadmklxfile{type-ini} % LMTX
+\loadmarkfile{type-set}
+
+\loadmarkfile{scrp-ini}
+
+\loadmarkfile{symb-emj}
+
+\loadmarkfile{lang-wrd} % can be optional (discussion with mm sideeffect)
+\loadmarkfile{lang-rep} % can be optional (bt 2013 side effect)
+
+\loadmarkfile{prop-ini} % only for downward compatibility
+
+\loadmkxlfile{mlib-ctx} % messy order
+
+\loadmarkfile{meta-ini}
+\loadmarkfile{meta-tex}
+\loadmarkfile{meta-fun}
+\loadmarkfile{meta-pag}
+\loadmarkfile{meta-grd}
+\loadmarkfile{meta-fnt}
+\loadmarkfile{meta-nod}
+\loadmarkfile{meta-lua}
+\loadmkxlfile{meta-mac}
+
+\loadmarkfile{page-mrk} % depends on mp
+
+\loadmarkfile{page-flw}
+\loadmarkfile{page-spr}
+\loadmarkfile{page-plg}
+\loadmarkfile{page-str}
+
+\loadmarkfile{anch-pgr} % can be moved up (nicer for dependencies)
+\loadmkvifile{anch-bck}
+\loadmarkfile{anch-tab} % overloads tabl-tbl
+\loadmarkfile{anch-bar}
+%loadmarkfile{anch-snc} % when needed this one will be redone
+
+\loadmarkfile{math-ini} % way after font-pre !
+\loadmarkfile{math-pln}
+\loadmarkfile{math-for}
+\loadmarkfile{math-def} % also saves some meanings
+\loadmarkfile{math-ali}
+%loadmarkfile{math-arr}
+\loadmkvifile{math-stc}
+\loadmarkfile{math-frc}
+\loadmarkfile{math-mis}
+\loadmarkfile{math-scr}
+\loadmarkfile{math-int}
+\loadmarkfile{math-del}
+\loadmarkfile{math-fen}
+\loadmkvifile{math-acc}
+\loadmkvifile{math-rad}
+\loadmarkfile{math-inl}
+\loadmarkfile{math-dis}
+%loadmarkfile{math-lan}
+
+%loadmarkfile{phys-dim} % moved to after typo-scr
+
+\loadmarkfile{strc-mat}
+
+\loadmarkfile{chem-ini}
+\loadmarkfile{chem-str}
+
+\loadmarkfile{typo-scr}
+\loadmarkfile{phys-dim}
+
+\loadmarkfile{node-rul} % beware, defined \underbar so after math
+\loadmkvifile{font-sol} % font solutions
+
+\loadmkvifile{strc-not}
+\loadmkvifile{strc-lnt}
+\loadmkivfile{strc-tnt}
+\loadmkivfile{strc-usr}
+
+\loadmarkfile{pack-com}
+\loadmarkfile{typo-del}
+
+\loadmarkfile{grph-trf}
+\loadmarkfile{grph-inc}
+\loadmarkfile{grph-fig}
+\loadmarkfile{grph-raw}
+\loadmarkfile{grph-rul}
+\loadmarkfile{grph-pat}
+
+\loadmarkfile{pack-box}
+\loadmarkfile{pack-bar}
+\loadmarkfile{page-app}
+\loadmarkfile{meta-fig}
+
+\loadmarkfile{page-ffl}
+
+\loadmarkfile{lang-spa} % will become obsolete
+
+\loadmarkfile{typo-ovl} % fuzzy project (tracing) code
+
+% old bibtex support: (will be m-oldbibtex.mkiv)
+
+% \loadmarkfile{bibl-bib}
+% \loadmarkfile{bibl-tra}
+
+% new bibtex support:
+
+\loadmarkfile{publ-ini}
+\loadmarkfile{publ-tra}
+\loadmarkfile{publ-xml}
+\loadmarkfile{publ-old}
+
+%loadmarkfile{x-xtag} % no longer preloaded
+
+\loadmarkfile{meta-xml}
+
+\loadmarkfile{cont-log}
+
+% \loadmarkfile{task-ini}
+
+\loadmarkfile{cldf-ver} % verbatim, this can come late
+\loadmarkfile{cldf-com} % commands, this can come late
+
+\loadmarkfile{core-ctx} % this order might change but we need to check depedencies / move to another namespace
+
+\loadmarkfile{core-def}
+
+%usemodule[x][res-04] % xml resource libraries
+%usemodule[x][res-08] % rlx runtime conversion
+%usemodule[x][res-12] % rli external indentification
+
+% now we hook in backend code (needs checking)
+
+\loadmkxlfile{driv-shp}
+
+\loadmarkfile{back-exp}
+\loadmkxlfile{back-pdf}
+\loadmkxlfile{back-mps}
+\loadmkxlfile{back-lua}
+
+\loadmarkfile{mlib-pdf}
+\loadmarkfile{mlib-pps}
+\loadmarkfile{meta-pdf}
+\loadmarkfile{meta-blb}
+\loadmarkfile{grph-epd}
+
+\loadmarkfile{math-inc} % an experiment
+\loadmarkfile{publ-inc} % an experiment
+
+\loadmarkfile{task-ini}
+
+\loadmarkfile{syst-cmp} % compatibility stuff moved here
+
+\loadmarkfile{cont-run} % the main runner (used in cont-yes.mkiv)
+
+% \loadmkxlfile{driv-shp}
+
+\appendtoks
+ \setupoutput[pdf]
+\to \everyjob
+
+\setupcurrentlanguage[\defaultlanguagetag]
+
+\prependtoks
+ \ctxlua{statistics.starttiming(statistics)}%
+\to \everyjob
+
+\appendtoks
+ \ctxlua{statistics.stoptiming(statistics)}%
+\to \everyjob
+
+% \appendtoks
+% \ctxlua{job.prepare()}%
+% \to \everyjob
+
+% \appendtoks
+% \enabletrackers[*]%
+% \to \everyjob
+
+\appendtoks
+ \ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkxl","\contextkind","\contextbanner")}% can become automatic
+\to \everydump
+
+\errorstopmode \dump \endinput
diff --git a/tex/context/base/mkiv/core-lmt.mkiv b/tex/context/base/mkiv/core-lmt.mkxl
index eda667969..75a791a50 100644
--- a/tex/context/base/mkiv/core-lmt.mkiv
+++ b/tex/context/base/mkiv/core-lmt.mkxl
@@ -1,6 +1,6 @@
%D \module
%D [ file=core-lmt,
-%D version=2010.08.2,
+%D version=2018.08.2,
%D title=\CONTEXT\ System Macros,
%D subtitle=Primitives,
%D author=Hans Hagen,
@@ -11,13 +11,12 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\ifcase\contextlmtxmode\expandafter\endinput\fi
-
\writestatus{loading}{ConTeXt System Macros / Primitives}
-\ifdefined\textdir \else
- \registerctxluafile{core-lmt}{}
-\fi
+%D This is offered temporarily because in the end we don't expect u sers to use the
+%D low level direction directives directly.
+
+\registerctxluafile{core-lmt}{}
\unprotect
diff --git a/tex/context/base/mkiv/data-tmp.lua b/tex/context/base/mkiv/data-tmp.lua
index e65f7ce61..ae7f65149 100644
--- a/tex/context/base/mkiv/data-tmp.lua
+++ b/tex/context/base/mkiv/data-tmp.lua
@@ -69,7 +69,8 @@ caches.ask = false
caches.relocate = false
caches.defaults = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
-directives.register("system.caches.fast",function(v) caches.fast = true end)
+directives.register("system.caches.fast", function(v) caches.fast = true end)
+directives.register("system.caches.direct",function(v) caches.direct = true end)
local writable, readables, usedreadables = nil, { }, { }
@@ -361,11 +362,7 @@ end
local saveoptions = { compact = true }
--- add some point we will only use the internal bytecode compiler and
--- then we can flag success in the tma so that it can trigger a compile
--- if the other engine
-
-function caches.savedata(filepath,filename,data,raw)
+function caches.savedata(filepath,filename,data)
local tmaname, tmcname = caches.setluanames(filepath,filename)
data.cache_uuid = os.uuid()
if caches.fast then
diff --git a/tex/context/base/mkiv/driv-ini.mkiv b/tex/context/base/mkiv/driv-ini.mkiv
index 958afb6a9..96e7460a3 100644
--- a/tex/context/base/mkiv/driv-ini.mkiv
+++ b/tex/context/base/mkiv/driv-ini.mkiv
@@ -13,19 +13,18 @@
\writestatus{loading}{ConTeXt Driver Macros / Initialization}
+%D Around the \CONTEXT\ 2018 meeting I had a preliminary backend written in \LUA\ as
+%D alternative for the hard coded variant (we're talking of the font embedding and
+%D page stream output, the part we still used). Therefore there is a pluggable
+%D output driver. But \unknown\ I decided not to waste time on supporting both
+%D \LUATEX\ and the new kid \LUAMETATEX, also because in practice \LUATEX\ would be
+%D used as benchmark, using the more traditional approach. So, the code in the
+%D driver modules is mostly a kind of simple placeholder now and although I could
+%D simplify it ther eis no real reason for it. It is no problem to getit all working
+%D well in normal \LUATEX, it's just that we don't need it there.
+
\registerctxluafile{driv-ini}{}
\unprotect
-\unexpanded\def\page_shipout_box#1%
- {\clf_shipoutpage#1\relax
- \global\setbox#1\emptybox
- \global\deadcycles\zerocount}
-
-\ifdefined\page_otr_shipout_yes \else
-
- \let\page_otr_shipout_yes\page_shipout_box
-
-\fi
-
\protect \endinput
diff --git a/tex/context/base/mkiv/driv-ini.mkxl b/tex/context/base/mkiv/driv-ini.mkxl
new file mode 100644
index 000000000..9f489a2a1
--- /dev/null
+++ b/tex/context/base/mkiv/driv-ini.mkxl
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=driv-ini,
+%D version=2018.07.26,
+%D title=\CONTEXT\ Driver Macros,
+%D subtitle=Initialization,
+%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.
+
+\writestatus{loading}{ConTeXt Driver Macros / Initialization}
+
+\registerctxluafile{driv-ini}{}
+
+\unprotect
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/driv-shp.mkiv b/tex/context/base/mkiv/driv-shp.mkxl
index f92649a48..68b62c72a 100644
--- a/tex/context/base/mkiv/driv-shp.mkiv
+++ b/tex/context/base/mkiv/driv-shp.mkxl
@@ -11,14 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\ifcase\contextlmtxmode \else
- \registerctxluafile{driv-shp}{optimize}
-\fi
+\registerctxluafile{driv-shp}{optimize}
\unprotect
-\appendtoks
- \clf_enabledriver{pdf}%
-\to \everyjob
-
\protect \endinput
diff --git a/tex/context/base/mkiv/file-job.lua b/tex/context/base/mkiv/file-job.lua
index 486aee63a..fd9a5a120 100644
--- a/tex/context/base/mkiv/file-job.lua
+++ b/tex/context/base/mkiv/file-job.lua
@@ -172,8 +172,8 @@ implement {
-- moved from tex to lua:
-local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.tex" }
-local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua" }
+local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.mklx", "%s.mkxl", "%s.tex" }
+local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua", "%s.lmt" }
local cldpatterns = { "%s.cld" }
local xmlpatterns = { "%s.xml" }
diff --git a/tex/context/base/mkiv/file-mod.lua b/tex/context/base/mkiv/file-mod.lua
index 81320f96e..10a187178 100644
--- a/tex/context/base/mkiv/file-mod.lua
+++ b/tex/context/base/mkiv/file-mod.lua
@@ -36,7 +36,7 @@ local iterator = utilities.parsers.iterator
-- modules can have a specific suffix or can specify one
-local prefixes = {
+local prefixes = {
"m", -- module, extends functionality
"p", -- private code
"s", -- styles
@@ -47,13 +47,24 @@ local prefixes = {
-- the order might change and how about cld
-local suffixes = {
- "mkvi", -- proprocessed mkiv files
+local suffixes = CONTEXTLMTXMODE > 0 and
+{
+ "mklx", -- preprocessed mkiv lmtx files
+ "mkxl", -- mkiv lmtx files
+ "mkvi", -- preprocessed mkiv files
"mkiv", -- mkiv files
"tex", -- normally source code files
"cld", -- context lua documents (often stand alone)
"lua", -- lua files
}
+ or
+{
+ "mkvi",
+ "mkiv",
+ "tex",
+ "cld",
+ "lua",
+}
local modstatus = { }
local missing = false
diff --git a/tex/context/base/mkiv/font-emp.mklx b/tex/context/base/mkiv/font-emp.mklx
new file mode 100644
index 000000000..7eaf0a24f
--- /dev/null
+++ b/tex/context/base/mkiv/font-emp.mklx
@@ -0,0 +1,256 @@
+%D \module
+%D [ file=font-emp,
+%D version=20120106, % (moved from font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Emphasis,
+%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.
+
+\writestatus{loading}{ConTeXt Font Macros / Emphasis}
+
+\unprotect
+
+%D \macros
+%D {em,emphasistypeface,emphasisboldface}
+%D
+%D The next macro started as a copy of Donald Arseneau's \type {\em} (\TUGNEWS\
+%D Vol.~3, no.~1, 1994). His implementation was a bit more sophisticated version of
+%D the standard \LATEX\ one. We further enhanced the macro, so now it also adapts
+%D itself to boldface mode. Because we favor {\sl slanted} type over {\it italic},
+%D we made the emphasis adaptable, for instance:
+%D
+%D \starttyping
+%D \def\emphasistypeface {\it}
+%D \def\emphasisboldface {\bi}
+%D \stoptyping
+%D
+%D But we prefer:
+%D
+%D \starttyping
+%D \unexpanded\def\emphasistypeface{\sl}
+%D \unexpanded\def\emphasisboldface{\bs}
+%D \stoptyping
+%D
+%D or even better:
+
+\let\m_font_emphasized_typeface\empty
+
+\def\font_emphasis_checked_typeface#slanted#italic%
+ {\edef\m_font_emphasized_typeface{\font_bodyfontvariable\s!em}%
+ \ifx\m_font_emphasized_typeface\v!slanted
+ #slanted%
+ \orelse\ifx\m_font_emphasized_typeface\v!italic
+ #italic%
+ \orelse\ifx\m_font_emphasized_typeface\empty
+ #slanted%
+ \else
+ \csname\m_font_emphasized_typeface\endcsname
+ \fi}
+
+\unexpanded\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it}
+\unexpanded\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi}
+
+\unexpanded\def\normalboldface % public
+ {\relax
+ \ifx\fontalternative\s!it\bi\orelse
+ \ifx\fontalternative\s!sl\bs\else
+ \bf\fi}
+
+\unexpanded\def\normalitalicface % public
+ {\relax
+ \ifx\fontalternative\s!tf\it\orelse
+ \ifx\fontalternative\s!bf\bi\else
+ \tf\fi}
+
+\unexpanded\def\normalslantedface % public
+ {\relax \ifx\fontalternative\s!tf\sl
+ \orelse\ifx\fontalternative\s!bf\bs
+ \else \tf\fi}
+
+\unexpanded\def\normaltypeface % public
+ {\relax
+ \ifx\fontalternative\s!bi \it \orelse
+ \ifx\fontalternative\s!bs \sl \else
+ \tf \fi}
+
+\unexpanded\def\swaptypeface % public
+ {\relax
+ \ifx\fontalternative\s!it \tf \orelse
+ \ifx\fontalternative\s!sl \tf \orelse
+ \ifx\fontalternative\s!bf \emphasisboldface \orelse
+ \ifx\fontalternative\s!bs \bf \orelse
+ \ifx\fontalternative\s!bi \bf \else
+ \emphasistypeface \fi}
+
+\let\typeface \normaltypeface % public
+\let\boldface \normalboldface % public
+\let\slantedface\normalslantedface % public
+\let\italicface \normalitalicface % public
+\let\swapface \swaptypeface % public
+
+%D To be set with the default body font environment: \type
+%D {em} being \type {slanted} or \type {italic}.
+
+% maybe a \csname...\fontalternative\endcsname
+
+\newconditional\c_font_emphasis_needed
+
+\unexpanded\def\em
+ {\relax
+ \ifdim\slantperpoint>\zeropoint
+ \settrue\c_font_emphasis_needed
+ \else
+ \setfalse\c_font_emphasis_needed
+ \fi
+ \font_emphasis_set_emphasis_boldface % new
+ \ifx\fontalternative\s!it
+ \unexpanded\def\emphasistypeface{\it}\tf
+ \orelse\ifx\fontalternative\s!sl
+ \unexpanded\def\emphasistypeface{\sl}\tf
+ \orelse\ifx\fontalternative\s!bf
+ \emphasisboldface
+ \orelse\ifx\fontalternative\s!bs
+ \unexpanded\def\emphasisboldface{\bs}\bf
+ \orelse\ifx\fontalternative\s!bi
+ \unexpanded\def\emphasisboldface{\bi}\bf
+ \else
+ \emphasistypeface
+ \fi
+ \ifconditional\c_font_emphasis_needed\else
+ \expandafter\aftergroup
+ \fi
+ \emphasiscorrection}
+
+%D The next feature was not present in previous versions. It
+%D takes care of \type {\em \bf ...} situations.
+
+\let\font_emphasis_saved_emphasis_boldface\relax
+
+\def\font_emphasis_set_emphasis_boldface
+ {\let\font_emphasis_saved_emphasis_boldface\bf
+ \let\font_emphasis_set_emphasis_boldface\relax
+ \let\bf\font_emphasis_bold_bold}
+
+\unexpanded\def\font_emphasis_bold_bold
+ {%\relax
+ \let\bf\relax % new
+ \ifx\fontalternative\s!it
+ \bi
+ \orelse\ifx\fontalternative\s!sl
+ \bs
+ \else
+ \font_emphasis_saved_emphasis_boldface
+ \fi
+ \let\bf\font_emphasis_saved_emphasis_boldface}
+
+%D Donald's (adapted) macros take the next character into account when placing
+%D italic correction. As a bonus we also look for something that looks like a dash,
+%D in which case we don't correct.
+
+\let\italiccorrection=\/ % tex primitive
+
+\def\emphasiscorrection % public, not in raw alignment groups, else omit problem
+ {\ifhmode\ifnum\currentgrouptype=\aligngroupcode\else
+ \expandafter\expandafter\expandafter\font_emphasis_look
+ \fi\fi}
+
+\def\font_emphasis_look
+ {\begingroup
+ \futurelet\nexttoken\font_emphasis_test}
+
+\def\font_emphasis_test
+ {\ifcat\noexpand\nexttoken,% still ok?
+ \expandafter\font_emphasis_a
+ \else
+ \expandafter\font_emphasis_b
+ \fi}
+
+\def\font_emphasis_a
+ {\futurelet\nexttoken\font_emphasis_correction}
+
+\def\font_emphasis_correction
+ {\setbox\scratchbox\hbox{\nexttoken}% tricky as next can be a macro
+ \ifdim\ht\scratchbox=\zeropoint % probably a space
+ \expandafter\font_emphasis_b
+ \orelse\ifdim\ht\scratchbox<.3\exheight
+ \expandafter\expandafter\expandafter\endgroup
+ \else
+ \expandafter\expandafter\expandafter\font_emphasis_b
+ \fi}
+
+\def\font_emphasis_b
+ {\scratchskip\lastskip
+ \ifdim\scratchskip=\zeropoint\relax % == \ifzeropt\scratchskip
+ \italiccorrection\relax
+ \else
+ \unskip\italiccorrection\hskip\scratchskip
+ \fi
+ \endgroup}
+
+%D We end with some examples which show the behavior when some punctuation is met.
+%D We also show how the mechanism adapts itself to bold, italic and slanted typing.
+%D
+%D \startbuffer
+%D test {test}test \par
+%D test {\sl test}test \par
+%D test {\em test}test \par
+%D test {\em test}--test \par
+%D
+%D test {test}, test \par
+%D test {\em test}, test \par
+%D
+%D test {\em test {\em test {\em test} test} test} test \par
+%D test {\bf test {\em test {\em test} test} test} test \par
+%D test {\sl test {\em test {\em test} test} test} test \par
+%D test {\it test {\em test {\em test} test} test} test \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D We get:
+%D
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+
+%D \macros
+%D {emphbf,emphit,emphsl,emphtf}
+%D
+%D The next emphasis alternatives are for \THANH. They adapt their style as good as
+%D possible. These macros are obsolete in \MKIV.
+
+% \unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
+% \unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
+% \unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
+% \unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
+% \unexpanded\def\emph {\groupedcommand{\em}{}}
+
+\unexpanded\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}}
+\unexpanded\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}}
+\unexpanded\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}}
+\unexpanded\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}
+
+\unexpanded\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf}
+\unexpanded\def\emphit{\triggergroupedcommandcs\font_emphasis_it}
+\unexpanded\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl}
+\unexpanded\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf}
+\unexpanded\def\emph {\triggergroupedcommandcs\em}
+
+\unexpanded\def\emphasized{\bgroup\em\let\nexttoken}
+
+%D \startbuffer
+%D TEXT {\emphbf text \emphit text \emphtf text \emphsl text} TEXT
+%D TEXT \emphbf{text \emphit{text} \emphtf{text} \emphsl{text}} TEXT
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-emp.mkvi b/tex/context/base/mkiv/font-emp.mkvi
index b5c09d4c2..5dacd175b 100644
--- a/tex/context/base/mkiv/font-emp.mkvi
+++ b/tex/context/base/mkiv/font-emp.mkvi
@@ -18,13 +18,11 @@
%D \macros
%D {em,emphasistypeface,emphasisboldface}
%D
-%D The next macro started as a copy of Donald Arseneau's
-%D \type{\em} (\TUGNEWS\ Vol.~3, no.~1, 1994). His
-%D implementation was a bit more sophisticated version of the
-%D standard \LATEX\ one. We further enhanced the macro, so now
-%D it also adapts itself to boldface mode. Because we favor
-%D {\sl slanted} type over {\it italic}, we made the emphasis
-%D adaptable, for instance:
+%D The next macro started as a copy of Donald Arseneau's \type {\em} (\TUGNEWS\
+%D Vol.~3, no.~1, 1994). His implementation was a bit more sophisticated version of
+%D the standard \LATEX\ one. We further enhanced the macro, so now it also adapts
+%D itself to boldface mode. Because we favor {\sl slanted} type over {\it italic},
+%D we made the emphasis adaptable, for instance:
%D
%D \starttyping
%D \def\emphasistypeface {\it}
@@ -148,10 +146,9 @@
\fi\fi
\let\bf\font_emphasis_saved_emphasis_boldface}
-%D Donald's (adapted) macros take the next character into
-%D account when placing italic correction. As a bonus we also
-%D look for something that looks like a dash, in which case we
-%D don't correct.
+%D Donald's (adapted) macros take the next character into account when placing
+%D italic correction. As a bonus we also look for something that looks like a dash,
+%D in which case we don't correct.
\let\italiccorrection=\/ % tex primitive
@@ -193,9 +190,8 @@
\fi
\endgroup}
-%D We end with some examples which show the behavior when
-%D some punctuation is met. We also show how the mechanism
-%D adapts itself to bold, italic and slanted typing.
+%D We end with some examples which show the behavior when some punctuation is met.
+%D We also show how the mechanism adapts itself to bold, italic and slanted typing.
%D
%D \startbuffer
%D test {test}test \par
@@ -223,9 +219,8 @@
%D \macros
%D {emphbf,emphit,emphsl,emphtf}
%D
-%D The next emphasis alternatives are for \THANH. They adapt
-%D their style as good as possible. These macros are obsolete
-%D in \MKIV.
+%D The next emphasis alternatives are for \THANH. They adapt their style as good as
+%D possible. These macros are obsolete in \MKIV.
% \unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
% \unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
diff --git a/tex/context/base/mkiv/font-fil.mklx b/tex/context/base/mkiv/font-fil.mklx
new file mode 100644
index 000000000..6cc25db10
--- /dev/null
+++ b/tex/context/base/mkiv/font-fil.mklx
@@ -0,0 +1,422 @@
+%D \module
+%D [ file=font-fil,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Classes and Files,
+%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.
+
+\writestatus{loading}{ConTeXt Font Macros / Classes and Files}
+
+\unprotect
+
+%D Personally I think that using \TEX\ macro packages is complicated by the way
+%D fonts are handled. Apart from the many encodings, we also deal with different
+%D naming schemes. Confronted with this problem, I decided to change the definitions
+%D into:
+%D
+%D \starttyping
+%D \definebodyfont [12pt] [rm] [tf=Times-Roman at 12pt]
+%D \stoptyping
+%D
+%D combined with for instance:
+%D
+%D \starttyping
+%D \definefontsynonym [Times-Roman] [tir]
+%D \stoptyping
+
+% \definetypeface[palatino][rm][serif][palatino,allbold][default]
+%
+% \startfontclass[palatino]
+% \definefontsynonym [Serif] [SerifBold]
+% \definefontsynonym [SerifItalic] [SerifBoldItalic]
+% \definefontsynonym [SerifSlanted] [SerifBoldSlanted]
+% \definefontsynonym [SerifCaps] [SerifBold]
+% \stopfontclass
+%
+% \setupbodyfont[palatino]
+
+\unexpanded\def\startfontclass
+ {\dosingleempty\font_basics_start_font_class}
+
+\def\font_basics_start_font_class[#class]%
+ {\push_macro_fontclass
+ \doifelse{#class}\v!each
+ {\let\fontclass\empty}
+ {\doifsomething{#class}{\def\fontclass{#class}}}}
+
+\unexpanded\def\stopfontclass
+ {\pop_macro_fontclass}
+
+\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
+
+%D \macros
+%D {definefontsynonym, doifelsefontsynonym,
+%D expandfontsynonym, truefontname, truefontdata}
+%D
+%D While looking for fonts, fontsynonyms are used for accessing
+%D the files!
+%D
+%D \starttyping
+%D \definefontsynonym[Serif][Lucida-Bright]
+%D \definefontsynonym[Lucida-Bright][lbr][encoding=texnansi]
+%D \stoptyping
+
+\installcorenamespace {fontfile} % file synonyms
+
+\let\m_font_name\empty
+\let\m_font_file\empty
+
+\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
+\edef\nullfontname {\fontname\nullfont}
+
+\unexpanded\def\definefontsynonym[#name]#crap[#file]%
+ {\edef\m_font_name{#name}%
+ \edef\m_font_file{#file}%
+ \ifx\fontclass\empty
+ \expandafter\font_basics_define_font_synonym_nop
+ \else
+ \expandafter\font_basics_define_font_synonym_yes
+ \fi}
+
+\unexpanded\def\font_basics_define_font_synonym_nop
+ {\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
+ \doifelsenextoptionalcs\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil}
+
+\unexpanded\def\font_basics_define_font_synonym_yes
+ {\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
+ \doifelsenextoptionalcs\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil}
+
+\unexpanded\def\edefinefontsynonym[#name]#crap[#file]%
+ {\edef\m_font_name{#name}%
+ \edef\m_font_file{#file}%
+ \ifx\fontclass\empty
+ \expandafter\font_basics_define_font_synonym_nop_expanded
+ \else
+ \expandafter\font_basics_define_font_synonym_yes_expanded
+ \fi}
+
+\unexpanded\def\font_basics_define_font_synonym_nop_expanded#crap[#spec]%
+ {\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
+ \normalexpanded{\font_basics_define_font_synonym_nop_opt[#1]}}
+
+\unexpanded\def\font_basics_define_font_synonym_yes_expanded#crap[#spec]%
+ {\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
+ \normalexpanded{\font_basics_define_font_synonym_yes_opt[#spec]}}
+
+\unexpanded\def\font_basics_define_font_synonym_nop_opt[#specification]%
+ {\let\p_features \undefined
+ \let\p_fallbacks \undefined
+ \let\p_goodies \undefined
+ \let\p_designsize\undefined
+ \expandafter\font_basics_get_font_parameter_nop#specification,]=,}
+
+\unexpanded\def\font_basics_define_font_synonym_yes_opt[#specification]%
+ {\let\p_features \undefined
+ \let\p_fallbacks \undefined
+ \let\p_goodies \undefined
+ \let\p_designsize\undefined
+ \expandafter\font_basics_get_font_parameter_yes#specification,]=,}
+
+% todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that
+% can be default then: \let\mathsizesuffix\relax .. i need to play with it first
+
+\def\font_basics_get_font_parameter_nop#key=#value,%
+ {\if]#key%
+ \font_basics_get_font_parameter_nop_finish
+ \else
+ \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
+ \expandafter\font_basics_get_font_parameter_nop
+ \fi}
+
+\def\font_basics_get_font_parameter_yes#key=#value,%
+ {\if]#key%
+ \font_basics_get_font_parameter_yes_finish
+ \else
+ \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
+ \expandafter\font_basics_get_font_parameter_yes
+ \fi}
+
+% helpers, some day these will be toks and counts
+
+% \def\fntsetdefname {\glet\somefontname\defaultfontfile}
+% \def\fntsetsomename{\gdef\somefontname} % takes argument
+% \def\fntsetnopsize {\let\somefontsize\empty}
+% \def\fntsetsomesize{\def\somefontsize} % takes argument
+
+% happens later, else mkvi parsing gets into troubles
+
+% end of helpers
+
+% we could collect them in one macro (but no expansion)
+
+\def\font_basics_define_font_synonym_nop_nil
+ {\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!fallbacks \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!goodies \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\undefined}
+
+\def\font_basics_define_font_synonym_yes_nil
+ {\expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined}
+
+\def\font_basics_get_font_parameter_nop_finish
+ {\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\p_features
+ \expandafter\let\csname\??fontfile\m_font_name\s!fallbacks \endcsname\p_fallbacks
+ \expandafter\let\csname\??fontfile\m_font_name\s!goodies \endcsname\p_goodies
+ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\p_designsize}
+
+\def\font_basics_get_font_parameter_yes_finish
+ {\expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize}
+
+%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}]
+%
+%\defineclassfontsynonym [KopFont] [officina] [SerifBold]
+
+\unexpanded\def\defineclassfontsynonym
+ {\dotripleargument\font_basics_define_class_font_synonym}
+
+%\definefontsynonym[#tag][\fontclassname{#class}{#fileortag}]}
+
+\def\font_basics_define_class_font_synonym[#tag][#class][#fileortag]% needs testing
+ {\expandafter\normaldef\csname\??fontfile\fontclass#tag\endcsname{\fontclassname{#class}{#fileortag}}%
+ \font_basics_define_font_synonym_yes_nil}
+
+\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
+
+\unexpanded\def\setupfontsynonym
+ {\dodoubleempty\dosetupfontsynonym}
+
+\def\dosetupfontsynonym[#name][#settings]% not yet supported, will do when needed
+ {}
+
+% todo: replace * by ... less messy with features
+
+\def\truefontname#name%
+ {\expandafter\font_helpers_true_fontname#name*\empty*\relax}
+
+\def\font_helpers_true_fontname#name*#first#rest*#crap\relax
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ \ifx#first\empty
+ %\expandafter\truefontname\csname\??fontfile\fontclass#name\endcsname
+ \expandafter\truefontname\lastnamedcs
+ \else
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname*#first#rest%
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
+ \fi
+ \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ \ifx#first\empty
+ %\expandafter\truefontname\csname\??fontfile\defaultfontclass#name\endcsname
+ \expandafter\truefontname\lastnamedcs
+ \else
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname*#first#rest%
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
+ \fi
+ \orelse\ifcsname\??fontfile#name\endcsname
+ \ifx#first\empty
+ %\expandafter\truefontname\csname\??fontfile#name\endcsname
+ \expandafter\truefontname\lastnamedcs
+ \else
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname*#first#rest%
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
+ \fi
+ \else
+ #name\ifx#first\empty\else*#first#rest\fi
+ \fi}
+
+\def\font_helpers_true_fontname_check#name%
+ {\expandafter\font_helpers_true_fontname_check_indeed#name*\relax}
+
+\def\font_helpers_true_fontname_check_indeed#name*#crap\relax
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs
+ \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs
+ \orelse\ifcsname\??fontfile#name\endcsname
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs
+ \else
+ #name%
+ \fi}
+
+% ok when the last lookup is not stripped .. we need to be able to define synonyms for symbols
+%
+% \def\truefontname#name%
+% %{\normalexpanded{\noexpand\font_helpers_true_fontname{\clf_truefontname{#name}}}}
+% {\expandafter\expandafter\expandafter\font_helpers_true_fontname\expandafter\expandafter\expandafter{\clf_truefontname{#name}}}
+%
+% \def\font_helpers_true_fontname#name%
+% {\ifcsname\??fontfile\fontclass#name\endcsname
+% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}%
+% \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
+% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}%
+% \orelse\ifcsname\??fontfile#name\endcsname
+% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}%
+% \else
+% % \clf_truefontname{#name}%
+% #name% so the last one can have features !
+% \fi}
+
+\def\expandfontsynonym#command#name% one level expansion
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ %\expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\fontclass#name\endcsname}%
+ \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
+ \orelse\ifcsname\??fontfile\defaultfontclass#2\endcsname
+ %\expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\defaultfontclass#name\endcsname}%
+ \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
+ \fi}
+
+\def\doifelsefontsynonym#name%
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ \expandafter\firstoftwoarguments
+ \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiffontsynonymelse\doifelsefontsynonym
+
+%D \macros
+%D {tracedfontname}
+%D
+%D A goody:
+
+\def\tracedfontname#name%
+ {#name\ifcsname\??fontfile\fontclass#name\endcsname
+ %\expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname
+ \expandafter\tracedfontname\lastnamedcs
+ \orelse\ifcsname\??fontfile#name\endcsname
+ %\expandafter\tracedfontname\csname\??fontfile#name\endcsname
+ \expandafter\tracedfontname\lastnamedcs
+ \fi}
+
+%D \macros
+%D {fontclass, defaultfontclass}
+%D
+%D The fontclass model was introduced a while after we implement the basic font
+%D model and at that time we still defaulted to no model at all. Nowadays we default
+%D to the \type {modern} fontclass.
+
+\let\fontclass \empty
+\let\defaultfontclass\empty
+
+\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting
+ {\ifcsname\??fontfile#class#name\endcsname
+ \fontclassname{#class}{\csname\??fontfile#class#name\endcsname}%
+ \orelse\ifcsname\??fontfile#name\endcsname
+ \fontclassname{#class}{\csname\??fontfile#name\endcsname}%
+ \else
+ #2%
+ \fi}
+
+\installmacrostack\fontclass
+
+%D Files or names can have properties and these need to be consulted at some point.
+%D They can inherit them.
+
+% Why these expanded and rscale not ... maybe not worth the trouble (delayed
+% expansion actually would be better i.e. macros in feature specs). Test
+% without pre-expansion.
+
+\def\font_helpers_update_font_class_parameters
+ {\edef\m_font_class_direction {\begincsname\??fontclass\fontclass\fontstyle\s!direction \endcsname}%
+ \edef\m_font_class_features {\begincsname\??fontclass\fontclass\fontstyle\s!features \endcsname}%
+ \edef\m_font_class_fallbacks {\begincsname\??fontclass\fontclass\fontstyle\s!fallbacks \endcsname}%
+ \edef\m_font_class_goodies {\begincsname\??fontclass\fontclass\fontstyle\s!goodies \endcsname}%
+ \edef\m_font_class_designsize{\begincsname\??fontclass\fontclass\fontstyle\s!designsize\endcsname}}
+
+% resolve
+
+\def\font_helpers_set_features_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\orelse % class + symbolic_name
+ \ifcsname\??fontfile #name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\orelse % symbolic_name
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \orelse % class + parent_name
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \else % parent_name
+ \let\m_font_features\empty\fi}
+
+\def\font_helpers_set_fallbacks_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse
+ \ifcsname\??fontfile #name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \orelse
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \else
+ \let\m_font_fallbacks\empty\fi}
+
+\def\font_helpers_set_goodies_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\orelse
+ \ifcsname\??fontfile #name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\orelse
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \orelse
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \else
+ \let\m_font_goodies\empty\fi}
+
+\def\font_helpers_set_designsize_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse
+ \ifcsname\??fontfile #name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \orelse
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \else
+ \let\m_font_designsize\empty\fi}
+
+\def\font_helpers_set_features_nop#name%
+ {\ifcsname\??fontfile#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\orelse
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_features_nop\lastnamedcs \else
+ \let\m_font_features\empty\fi}
+
+\def\font_helpers_set_fallbacks_nop#name%
+ {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_fallbacks_nop\lastnamedcs \else
+ \let\m_font_fallbacks\empty\fi}
+
+\def\font_helpers_set_goodies_nop#name%
+ {\ifcsname\??fontfile#name\s!goodies\endcsname \edef\m_font_goodies{\lastnamedcs}\orelse
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_goodies_nop\lastnamedcs \else
+ \let\m_font_goodies\empty\fi}
+
+\def\font_helpers_set_designsize_nop#name%
+ {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_designsize_nop\lastnamedcs \else
+ \let\m_font_designsize\empty\fi}
+
+\def\font_helpers_update_font_parameters_yes
+ {\font_helpers_set_features_yes \somefontname
+ \font_helpers_set_fallbacks_yes \somefontname
+ \font_helpers_set_goodies_yes \somefontname
+ \font_helpers_set_designsize_yes\somefontname}
+
+\def\font_helpers_update_font_parameters_nop
+ {\font_helpers_set_features_nop \somefontname
+ \font_helpers_set_fallbacks_nop \somefontname
+ \font_helpers_set_goodies_nop \somefontname
+ \font_helpers_set_designsize_nop\somefontname}
+
+\def\font_helpers_update_font_parameters
+ {\ifx\fontclass\empty\font_helpers_update_font_parameters_nop\else\font_helpers_update_font_parameters_yes\fi}
+
+\installcorenamespace{fontclass}
+
+% we can pack them (don't use \setxvalue!)
+
+\unexpanded\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction%
+ {\letgvalue{\??fontclass\fontclass#style\s!rscale }#rscale%
+ \letgvalue{\??fontclass\fontclass#style\s!features }#features%
+ \letgvalue{\??fontclass\fontclass#style\s!fallbacks }#fallbacks%
+ \letgvalue{\??fontclass\fontclass#style\s!goodies }#goodies%
+ \letgvalue{\??fontclass\fontclass#style\s!designsize}#designsize%
+ \letgvalue{\??fontclass\fontclass#style\s!direction }#direction}% math
+
+% bonus
+
+\let\currentfontinstancespec\clf_currentfontinstancespec % expandable
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-fil.mkvi b/tex/context/base/mkiv/font-fil.mkvi
index ae83ef4c4..8622e733f 100644
--- a/tex/context/base/mkiv/font-fil.mkvi
+++ b/tex/context/base/mkiv/font-fil.mkvi
@@ -15,11 +15,10 @@
\unprotect
-%D Personally I think that using \TEX\ macro packages is
-%D complicated by the way fonts are handled. Apart from the
-%D many encodings, we also deal with different naming schemes.
-%D Confronted with this problem, I decided to change the
-%D definitions into:
+%D Personally I think that using \TEX\ macro packages is complicated by the way
+%D fonts are handled. Apart from the many encodings, we also deal with different
+%D naming schemes. Confronted with this problem, I decided to change the definitions
+%D into:
%D
%D \starttyping
%D \definebodyfont [12pt] [rm] [tf=Times-Roman at 12pt]
@@ -307,10 +306,9 @@
%D \macros
%D {fontclass, defaultfontclass}
%D
-%D The fontclass model was introduced a while after we implement
-%D the basic font model and at that time we still defaulted to
-%D no model at all. Nowadays we default to the \type {modern}
-%D fontclass.
+%D The fontclass model was introduced a while after we implement the basic font
+%D model and at that time we still defaulted to no model at all. Nowadays we default
+%D to the \type {modern} fontclass.
\let\fontclass \empty
\let\defaultfontclass\empty
@@ -326,8 +324,8 @@
\installmacrostack\fontclass
-%D Files or names can have properties and these need to be consulted
-%D at some point. They can inherit them.
+%D Files or names can have properties and these need to be consulted at some point.
+%D They can inherit them.
% Why these expanded and rscale not ... maybe not worth the trouble (delayed
% expansion actually would be better i.e. macros in feature specs). Test
diff --git a/tex/context/base/mkiv/font-ini.mklx b/tex/context/base/mkiv/font-ini.mklx
new file mode 100644
index 000000000..4b112322d
--- /dev/null
+++ b/tex/context/base/mkiv/font-ini.mklx
@@ -0,0 +1,2563 @@
+%D \module
+%D [ file=font-ini,
+%D version=1998.09.11, % (second)
+%D version=2001.02.20, % (third)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Initialization,
+%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.
+
+% todo: < 3 pt => 3pt
+% todo: check where more class usage
+% todo: split font-nam (style/alternative/size)
+% todo: split font-dim (scales etc)
+% todo: reconsider defaultfontclass
+%
+
+%D Watch out: as we define inside macros in sometimes special ways,
+%D an occasional \type {\normaldef} is used in order to please the
+%D \MKVI\ parser.
+
+%D Beware, we use a special set of parameters here:
+%D
+%D \starttabulate[|l|l|]
+%D \NC system variable (fixed) \NC \type {\s!text} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!script} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!scriptscript} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!x} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!xx} \NC \NR
+%D \NC variable (value) \NC \type {\v!big} \NC \NR
+%D \NC variable (value) \NC \type {\v!small} \NC \NR
+%D \NC constant (regular key) \NC \type {\c!interlinespace} \NC \NR
+%D \NC constant (regular key) \NC \type {\c!em} \NC \NR
+%D \stoptabulate
+%D
+%D The math related ones are similar to the ones used in \TEX\ itself,
+%D the size related ones show up as keywords in the user interface
+%D when switching sizes, and the two constants are used in key|/|value
+%D situations.
+
+%D We should consider design sizes ... maybe kick 'm out which removes
+%D the size code and simplifies things considerably. After all, there
+%D will be no latin modern math in sizes.
+
+\writestatus{loading}{ConTeXt Font Macros / Initialization}
+
+%D Documentation is somewhat messy as it contains bits and pieces of
+%D previous versions.
+
+\unprotect
+
+%D There are several ways to specify a font. Three of them are pure \TEX\ ones, the
+%D fourth one is new:
+%D
+%D \starttyping
+%D \font\name=cmr12
+%D \font\name=cmr12 at 10pt
+%D \font\name=cmr12 scaled 2
+%D \font\name=cmr12 sa 1.440
+%D \stoptyping
+%D
+%D The non||\TEX\ alternative \type{sa} stands for {\em scaled at}. This means as
+%D much as: scale the bodyfontsize with this factor. The scaled option is not that
+%D useful as one needs to know the design size.
+%D
+%D Because \type {sa} (scaled at) and \type {mo} (mapped on) are not low level \TEX\
+%D supported alternatives, we have to test for it ourselves. In doing so, we need an
+%D auxiliary \DIMENSION. We cannot use \type{\scratchdimen} because font loading can
+%D happen at any moment due to postponed loading. We could instead have used dirty
+%D grouping tricks, but this one works too.
+
+% \enableexperiments[fonts.autorscale]
+%
+% \starttypescript[mscore]
+% \definetypeface [mscore] [rm] [serif] [mscoretimes] [default]
+% \definetypeface [mscore] [ss] [sans] [mscorearial] [default] [rscale=auto] % 0.860]
+% \definetypeface [mscore] [tt] [mono] [mscorecourier] [default] [rscale=auto] % 1.065]
+% \definetypeface [mscore] [mm] [math] [times] [default] [rscale=auto] % 1.020]
+% \stoptypescript
+%
+% \starttext
+% \setupbodyfont[mscore,12pt]
+% \startTEXpage
+% test \ss test \tt test
+% \stopTEXpage
+% \stoptext
+
+% \definetypeface[one][rm][serif][computer-roman][default]
+% \definetypeface[two][rm][serif][computer-roman][default][rscale=.9]
+%
+% {\one \bf test \two test}
+% {\one \bf test \pushcurrentfont \two \popcurrentfont test}
+
+%D \macros
+%D {rm,ss,tt,hw,cg}
+%D
+%D Fonts are defined in separate files. When we define a font, we distinguish
+%D between several styles. In most cases we will use:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC roman regular serif \NC \type{\rm} \NC\FR
+%D \NC sansserif sans support \NC \type{\ss} \NC\MR
+%D \NC type teletype mono \NC \type{\tt} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D The number of styles is not limited to these three. When using Lucida Bright we
+%D can for instance also define:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC handwritten \NC \type{\hw} \NC\FR
+%D \NC calligraphic \NC \type{\cg} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Within such a font set (\type{cmr}) and style (\type{\rm}) we can define a number
+%D of text font alternatives:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC typeface \NC \type{\tf} \NC\FR
+%D \NC boldface \NC \type{\bf} \NC\MR
+%D \NC slanted \NC \type{\sl} \NC\MR
+%D \NC italic \NC \type{\it} \NC\MR
+%D \NC boldslanted \NC \type{\bs} \NC\MR
+%D \NC bolditalic \NC \type{\bi} \NC\MR
+%D \NC smallcaps \NC \type{\sc} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Internally fonts are stored as combination of size, style
+%D and alternative, e.g. \type{12pt}+\type{\ss}+\type{\bf}. Users are not confronted
+%D with sizes, but use the style or style+alternative to activate them.
+%D
+%D During the definition of a bodyfont one can also declare the available larger
+%D alternatives:
+%D
+%D \starttyping
+%D \tf \tfa \tfb \tfc ...
+%D \bf \bfa \bfb \bfc ...
+%D \sl \sla \slb \slc ...
+%D \stoptyping
+%D
+%D The smaller ones are automatically supplied and derived from
+%D the the bodyfont environment.
+%D
+%D \starttyping
+%D \tfx \tfxx
+%D \bfx \bfxx
+%D \slx \slxx
+%D \stoptyping
+%D
+%D There are only two smaller alternatives per style. The larger alternatives on the
+%D other hand have no limitations.
+%D
+%D These larger alternatives are mostly used in chapter and section titles or on
+%D title pages. When one switches to a larger alternative, the bold an other ones
+%D automatically adapt themselves:
+%D
+%D \startbuffer
+%D \tfd Hi \bf there\sl, here \tfb I \bf am
+%D \stopbuffer
+%D
+%S \startnarrower
+%D \typebuffer
+%S \stopnarrower
+%D
+%D therefore becomes:
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D Maybe this mechanism isn't always as logic, but as said before, we tried to make
+%D it as intuitive as possible.
+%D
+%D So a specific kind of glyph can be characterized by:
+%D
+%D \startnarrower
+%D family (cmr) + bodyfont (12pt) + style (rm) + alternative (bf) + size (a)
+%D \stopnarrower
+%D
+%D The last component (the size) is optional.
+%D
+%D We introduced \type {\tf} as command to call for the current normally sized
+%D typeface. This commands results in roman, sans serif, teletype or whatever style
+%D is in charge. Such rather massive switches of style sometimes take more
+%D processing time than comfortable. Of course there is a workaround for this: we
+%D can call fonts directly by means of commands like:
+%D
+%D \starttyping
+%D \rmtf \sssl \tttf \rmbsa
+%D \stoptyping
+%D
+%D One should realize that this fast calls have limitations, they lack for instance
+%D automatic super- and subscript support.
+%D
+%D This leaves us two more commands: \type {\tx} and \type {\txx}. These activate a
+%D smaller and even more smaller font than the current one and adapt themselves to
+%D the current alternative, so when \type {\bf} is active, \type {\tx} gives a
+%D smaller boldface, which in turn can be called directly by \type {\bfx}.
+%D
+%D These two smaller alternatives are specified by the bodyfont environment and
+%D therefore not necessarily have similar sizes as \type {\scriptsize} and \type
+%D {\scriptscriptsize}. The main reason for this incompatibility (which can easily
+%D be undone) lays in the fact that we often want a bit bigger characters than in
+%D math mode. In \CONTEXT\ for instance the \type {\tx} and \type {\txx} commands
+%D are used for surrogate \cap {smallcaps} which support both nesting and
+%D alternatives, like in {\bf \cap {a \cap {small} world}}, which was typeset by
+%D
+%D \starttyping
+%D \bf\cap{a \cap{small} world}
+%D \stoptyping
+%D
+%D And compare $\rm \scriptstyle THIS$ with the slightly larger \cap {THIS}:
+%D \ruledhbox {$\rm \scriptstyle scriptstyle: THIS$} or \ruledhbox {\cap {x style:
+%D THIS}} makes a big difference.
+%D
+%D The \type {x..d} sizes should be used grouped. If you don't group them, i.e. call
+%D them in a row, \CONTEXT\ will not be able to sort out your intention (\type {x}
+%D inside \type {d} inside \type {x}. etc.). The following table demonstrates this:
+%D
+%D \def\FontState{\setstrut\ruledhbox{\strut Hello}}
+%D
+%D \starttabulate[|||||]
+%D \HL
+%D \NC \rlap{\quad\bf grouped} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
+%D \HL
+%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
+%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
+%D \NC \type{\tf} \NC \tf \FontState \NC \tf \tx \FontState \NC \tf \txx \FontState \NC \NR
+%D \NC \type{\tfa} \NC \tfa \FontState \NC \tfa \tx \FontState \NC \tfa \txx \FontState \NC \NR
+%D \NC \type{\tfb} \NC \tfb \FontState \NC \tfb \tx \FontState \NC \tfb \txx \FontState \NC \NR
+%D \NC \type{\tfc} \NC \tfc \FontState \NC \tfc \tx \FontState \NC \tfc \txx \FontState \NC \NR
+%D \NC \type{\tfd} \NC \tfd \FontState \NC \tfd \tx \FontState \NC \tfd \txx \FontState \NC \NR
+%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
+%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
+%D \HL
+%D \stoptabulate
+%D
+%D \blank
+%D
+%D \starttabulate[|||||]
+%D \HL
+%D \NC \rlap{\quad\bf stacked} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
+%D \HL
+%D \NC \type{\tfx}
+%D \NC \tfx \FontState
+%D \NC \tfx \tx \FontState
+%D \NC \tfx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfxx}
+%D \NC \tfx\tfxx \FontState
+%D \NC \tfx\tfxx \tx \FontState
+%D \NC \tfx\tfxx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tf}
+%D \NC \tfx\tfxx\tf \FontState
+%D \NC \tfx\tfxx\tf \tx \FontState
+%D \NC \tfx\tfxx\tf \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfa}
+%D \NC \tfx\tfxx\tf\tfa \FontState
+%D \NC \tfx\tfxx\tf\tfa \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfb}
+%D \NC \tfx\tfxx\tf\tfa\tfb \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfc}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfd}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfx}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfxx}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \txx \FontState
+%D \NC \NR
+%D \HL
+%D \stoptabulate
+
+\fontslantperpoint \nullfont 0\scaledpoint
+\fontinterwordspace \nullfont 256377\scaledpoint
+\fontinterwordstretch\nullfont 128188\scaledpoint
+\fontinterwordshrink \nullfont 85459\scaledpoint
+\fontexheight \nullfont 338952\scaledpoint
+\fontemwidth \nullfont 786432\scaledpoint
+\fontextraspace \nullfont 85459\scaledpoint
+
+\appendtoks
+ \fontslantperpoint \nullfont 0\scaledpoint
+ \fontinterwordspace \nullfont 256377\scaledpoint
+ \fontinterwordstretch\nullfont 128188\scaledpoint
+ \fontinterwordshrink \nullfont 85459\scaledpoint
+ \fontexheight \nullfont 338952\scaledpoint
+ \fontemwidth \nullfont 786432\scaledpoint
+ \fontextraspace \nullfont 85459\scaledpoint
+\to \everyjob
+
+%D Tracing
+
+\newtoks\t_font_tracers_definitions
+
+\unexpanded\def\tracefontdefinitions
+ {\the\t_font_tracers_definitions}
+
+%D Some housekeeping macros:
+
+\unexpanded\def\setfontparameters
+ {\setfalse\c_font_synchronize
+ \the\everybodyfont
+ \settrue\c_font_synchronize}
+
+\let\savedfont\empty
+
+\installmacrostack\savedfont
+
+\unexpanded\def\savefont
+ {\edef\savedfont{\the\font}% gives \csname
+ \push_macro_savedfont}
+
+\unexpanded\def\restorefont
+ {\pop_macro_savedfont
+ \savedfont}
+
+\unexpanded\def\pushcurrentfont
+ {\edef\popcurrentfont
+ {\def\noexpand\fontbody {\fontbody}%
+ \def\noexpand\fontstyle {\fontstyle}%
+ \def\noexpand\fontalternative{\fontalternative}%
+ \def\noexpand\fontsize {\fontsize}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}}
+
+%D \macros{definedfont}
+
+\let\thedefinedfont\relax % not to be confused with \everydefinefont
+
+\unexpanded\def\definedfont
+ {\doifelsenextoptionalcs\font_basics_defined_font_yes\font_basics_defined_font_nop}
+
+\def\font_basics_defined_font_yes[#specification]%
+ {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
+ \thedefinedfont
+ \the\everydefinedfont}
+
+\def\font_basics_defined_font_nop
+ {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \thedefinedfont
+ \the\everydefinedfont}
+
+%D \macros{startfont}
+
+\unexpanded\def\startfont{\begingroup\definedfont}
+\unexpanded\def\stopfont {\endgroup}
+
+%D \macros
+%D {everybodyfont,everyglobalbodyfont}
+%D
+%D Every change in bodyfont size has conseqences for the baseline distance and skips
+%D between paragraphs. These are initialized in other modules. Here we only provide
+%D the hooks that garantees their handling.
+%D
+%D At the system level one can initialize thing like:
+%D
+%D \starttyping
+%D \appendtoks \setupspacing \to \everybodyfont
+%D \stoptyping
+
+%D \macros
+%D {globalbodyfontsize,localbodyfontsize,bodyfontsize}
+%D
+%D Here we have to distinguish between the global (overal) bodyfont size and the
+%D local (sometimes in the textflow) size. We store these dimensions in two
+%D \DIMENSION\ registers. These registers are not to be misused in calculations.
+
+\ifdefined\globalbodyfontsize\else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
+\ifdefined\localbodyfontsize \else \newdimen\localbodyfontsize \fi \localbodyfontsize =\globalbodyfontsize
+\ifdefined\bodyfontsize \else \newdimen\bodyfontsize \fi \bodyfontsize =\globalbodyfontsize
+
+%D When we assign for instance 12pt to a \DIMENSION\ register the \type {\the}'d
+%D value comes out as 12.0pt, which is often not the way users specify the bodyfont
+%D size. Therefore we use normalized values. They are cached to save overhead in
+%D \LUA\ calls.
+
+\installcorenamespace{fontnormalizedbody}
+
+\def\normalizebodyfontsize#macro#body%
+ {\expandafter\let\expandafter#macro\csname\??fontnormalizedbody\number\dimexpr#body\endcsname
+ \ifx#macro\relax
+ \normalizebodyfontsize_indeed#macro{#body}%
+ \fi}
+
+\def\normalizebodyfontsize_indeed#macro#body%
+ {\edef#macro{\clf_nbfs\dimexpr#body\relax}%
+ \expandafter\glet\csname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro}
+
+\def\thenormalizedbodyfontsize#body%
+ {\clf_nbfs\dimexpr#body\relax}
+
+\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}
+\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+
+%D \macros
+%D {mapfontsize}
+%D
+%D For special purposes, like in math, you may want to use slightly different sizes
+%D than the ones given. This happens for instance with the Math Times fonts. Mapped
+%D font sizes can be specified by using the \type {mo} key instead of \type {sa} in
+%D font definitions.
+%D
+%D \startbuffer
+%D \mapfontsize[10pt][11pt]
+%D \mapfontsize[11pt][12pt]
+%D \mapfontsize[12pt][13pt]
+%D
+%D \definefont[test][Serif]\test TEST \par
+%D \definefont[test][Serif sa 5]\test TEST \par
+%D \definefont[test][Serif mo 5]\test TEST \par
+%D \definefont[test][Serif sa d]\test TEST \par
+%D \definefont[test][Serif at 60pt]\test TEST \par
+%D \definefont[test][Serif scaled 6000]\test TEST \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+
+\installcorenamespace{mappedfontsize}
+
+\unexpanded\def\mapfontsize
+ {\dodoubleargument\font_basics_map_fontsize}
+
+\def\font_basics_map_fontsize[#from][#to]%
+ {\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}}
+
+\def\font_basics_set_mapped_fontsize#from%
+ {\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname
+ \lastnamedcs\else#from%
+ \fi}
+
+\installcorenamespace{fontbodyknown}
+\installcorenamespace{fontclassyes} % fontclass
+\installcorenamespace{fontclassnop} % nofontclass
+
+\def\font_helpers_process_relative_size_list#command% could be a toks
+ {#command\v!big
+ #command\v!small}
+
+\let\v_font_size_relative \plusone
+\def\v_font_size_absolute {\fontbody}
+
+\let\v_font_rscale_default\!!plusone
+\let\p_font_rscale \v_font_rscale_default
+
+\def\font_helpers_check_relative_font_id % can be plugged in later
+ {\let\p_font_rscale\minusone
+ \let\p_font_rscale\v_font_rscale_default}
+
+\def\font_helpers_check_relative_font_size#style%
+ {\edef\p_font_rscale
+ {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??fontclass\defaultfontclass#style\s!rscale\endcsname % brr
+ \lastnamedcs
+ \else
+ \v_font_rscale_default
+ \fi}%
+ % move elsewhere
+ \ifx\p_font_rscale\v!auto
+ \let\p_font_rscale\plusone
+ \font_helpers_check_relative_font_id
+ \else
+ \let\relativefontid\minusone
+ \fi}
+
+\def\font_rscale_xx#style%
+ {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
+ \lastnamedcs
+ \else
+ \v_font_rscale_default
+ \fi}
+
+\def\font_rscale_mm
+ {\ifcsname\??fontclass\fontclass\s!mm\s!rscale\endcsname
+ \lastnamedcs
+ \else
+ \v_font_rscale_default
+ \fi}
+
+\def\font_helpers_register_fontbody#body%
+ {\expandafter\let\csname\??fontbodyknown#body\endcsname\empty}
+
+%D \macros
+%D {definefontstyle,definefontsize,definefontalternative}
+%D
+%D When setting of switching the overall style we can use the short identifier like
+%D rm and ss, but when defined we can also use more verbose names like roman or
+%D sansserif. Such names are defined by:
+%D
+%D \starttyping
+%D \definefontstyle [serif,rm] [rm]
+%D \definefontstyle [sansserif,ss] [ss]
+%D \stoptyping
+
+\installcorenamespace{fontstyle} % full style prefix (roman etc)
+\installcorenamespace{fontshortstyle} % short style prefix (rm etc)
+
+\installcorenamespace{fontstyleknown}
+\installcorenamespace{fontalternativeknown}
+\installcorenamespace{fontsizeknown}
+
+\newtoks\t_font_style_commands
+\newtoks\t_font_size_commands
+\newtoks\t_font_alternative_commands
+
+\setnewmacro\m_font_style_command \gobbleoneargument
+\setnewmacro\m_font_size_command \gobbleoneargument
+\setnewmacro\m_font_alternative_command\gobbleoneargument
+
+\def\font_helpers_process_style_list #command{\def\m_font_style_command {#command}\the\t_font_style_commands}
+\def\font_helpers_process_size_list #command{\def\m_font_size_command {#command}\the\t_font_size_commands}
+\def\font_helpers_process_alternative_list#command{\def\m_font_alternative_command{#command}\the\t_font_alternative_commands}
+
+\def\font_helpers_register_style #style{\expandafter\let\csname\??fontstyleknown #style\endcsname\empty}
+\def\font_helpers_register_size #size{\expandafter\let\csname\??fontsizeknown #size\endcsname\empty}
+\def\font_helpers_register_alternative#alternative{\expandafter\let\csname\??fontalternativeknown#alternative\endcsname\empty}
+
+\unexpanded\def\definefontstyle
+ {\dodoubleargument\font_basics_define_fontstyle}
+
+\def\font_basics_define_fontstyle[#commands][#style]% style: rm ss tt ...
+ {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw)
+ \font_helpers_register_style{#style}%
+ \toksapp\t_font_style_commands{\m_font_style_command{#style}}%
+ \fi
+ \processcommalist[#commands]{\font_basics_define_fontstyle_indeed{#style}}}
+
+\def\font_basics_define_fontstyle_indeed#style#command%
+ {\setvalue{\??fontshortstyle#command}{#style}%
+ \setvalue{\??fontstyle #command}{\csname#style\endcsname}}
+
+\unexpanded\def\definefontsize[#size]%
+ {\ifcsname\??fontsizeknown#size\endcsname \else
+ \font_helpers_register_size{#size}%
+ \toksapp\t_font_size_commands{\m_font_size_command{#size}}%
+ \fi
+ \font_helpers_check_fontname_combinations}
+
+\unexpanded\def\definefontalternative[#alternative]%
+ {\ifcsname\??fontalternativeknown#alternative\endcsname \else
+ \font_helpers_register_alternative{#alternative}%
+ \toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}%
+ \fi
+ \font_helpers_check_fontname_combinations}
+
+\unexpanded\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb)
+ {\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s}
+
+\def\font_helpers_check_fontname_combinations_s#style%
+ {\font_helpers_process_alternative_list{\font_helpers_check_fontname_combinations_indeed_s_a{#style}}}
+
+\def\font_helpers_check_fontname_combinations_indeed_s_a#style#alternative%
+ {\font_helpers_process_size_list{\font_basics_check_fontname_combination{#style}{#alternative}}}
+
+\definefontstyle [\s!mm] [\s!mm]
+\definefontstyle [\s!rm] [\s!rm]
+\definefontstyle [\s!ss] [\s!ss]
+\definefontstyle [\s!tt] [\s!tt]
+
+%D We define all the font switching commands globally. After all they are part of
+%D the formal font interface once defined. The size can be empty (so checking is
+%D needed as \type {\bf} is already defined).
+%D
+%D The \type {\normal..} variants are available as extras for cases where the \type
+%D {..} is overloaded.
+
+\newmacro\m_font_mm
+
+\def\font_basics_check_fontname_combination#style% alternative size
+ {\edef\m_font_mm{#style}%
+ \ifx\m_font_mm\s!mm % prevents \max and alike (re)defs
+ \expandafter\font_basics_check_math_bodyfont
+ \else
+ \expandafter\font_basics_check_text_bodyfont
+ \fi{#style}} % no \m_font_mm, not expanded later on
+
+\def\font_basics_check_math_bodyfont#style#alternative#size%
+ {}
+
+\def\font_basics_check_text_bodyfont_step#whatever#body% size can be empty (checking needed as \bf is already defined)
+ {\ifcsname#whatever\endcsname\else
+ \setugvalue{#whatever}{#body}%
+ \fi}
+
+\def\font_basics_check_text_bodyfont#style#alternative#size% size can be empty (checking needed as \bf is already defined)
+ {\font_basics_check_text_bodyfont_step{#style#size}{\font_helpers_set_current_font_style_size{#style}{#size}}% \rma
+ \font_basics_check_text_bodyfont_step{#alternative#size}{\font_helpers_set_current_font_alternative_size{#alternative}{#size}}% \sla
+ \font_basics_check_text_bodyfont_step{#style#alternative#size}{\font_helpers_set_current_font_style_alternative_size{#style}{#alternative}{#size}}% \rmsla
+ \font_basics_check_text_bodyfont_step{#style}{\font_helpers_set_current_font_style{#style}}% \rm
+ \font_basics_check_text_bodyfont_step{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \sl
+ \font_basics_check_text_bodyfont_step{#style\s!x }{\font_helpers_set_current_font_x_style_alternative{#style}}% \rmx
+ \font_basics_check_text_bodyfont_step{#style\s!xx}{\font_helpers_set_current_font_xx_style_alternative{#style}}% \rmxx
+ \font_basics_check_text_bodyfont_step{#alternative\s!x }{\font_helpers_set_current_font_x_alternative{#alternative}}% \slx
+ \font_basics_check_text_bodyfont_step{#alternative\s!xx}{\font_helpers_set_current_font_xx_alternative{#alternative}}% \slxx
+ \font_basics_check_text_bodyfont_step{#style#alternative}{\font_helpers_set_current_font_style_alternative{#style}{#alternative}}}% \rmsl
+
+%D Scaling macros:
+%D
+%D This system is somewhat complicated by two (possible conflicting) demands:
+%D
+%D \startitemize
+%D \item We support wildcards like \type {sa *} which will adapt to the current
+%D size. This is also the default specification.
+%D \item We support named scales like \type {sa d}; beware: \type {x} and \type {xx}
+%D are valid scales but they are not alway the same as the ones used in for
+%D instance \type {\bfx} because there the sized come from the bodyfont
+%D environment. In the future there maybe a switch that also honors the
+%D environment in named scales.
+%D \stopitemize
+%D
+%D Keep in mind that the smaller sizes are just for text super and subscripts while
+%D larger sizes can be used in titles where for instance math follows the size.
+
+% b:x{\definedfont[SerifBold sa b]x}{\bfb x $x^x$}\par
+% 1:x{\definedfont[SerifBold sa 1]x}{\bf x $x^x$}\par
+% x:x{\definedfont[SerifBold sa x]x}{\bfx x $x^x$}\par
+% xx:x{\definedfont[SerifBold sa xx]x}{\bfxx x $x^x$}\par
+%
+% *:x{\definedfont[Serif sa *]x}\par
+% 1:x{\definedfont[Serif sa 1]x}\par
+% 2:x{\definedfont[Serif sa 2]x}\par
+% 3:x{\definedfont[Serif sa 3]x}\par
+% 4:x{\definedfont[Serif sa 4]x}\par
+% 5:x{\definedfont[Serif sa 5]x}\par
+
+\def\safontscale{\number\dimexpr\v_font_size_absolute\relax}
+\def\mofontscale{\number\dimexpr\font_basics_set_mapped_fontsize\v_font_size_absolute\relax}
+
+\let\somefontname\s!unknown
+\let\somefontspec\s!unknown
+\let\somefontsize\zerocount
+
+\newcount\scaledfontmode % also used at the lua end
+\newcount\scaledfontsize % also used at the lua end
+\newcount\lastfontid % also used at the lua end / tex end
+\newtoks \everydefinefont
+
+\let\relativefontid\minusone % todo, not yet used
+
+\let\c_font_feature_inheritance_fontnone \zerocount % none
+\let\c_font_feature_inheritance_fontonly \plusone % fontonly
+\let\c_font_feature_inheritance_classonly \plustwo % classonly
+\let\c_font_feature_inheritance_fontfirst \plusthree % fontfirst
+\let\c_font_feature_inheritance_classfirst\plusfour % classfirst
+
+\let\c_font_feature_inheritance_default \c_font_feature_inheritance_fontfirst
+
+\setnewconstant\c_font_feature_inheritance_mode \c_font_feature_inheritance_default
+
+\newdimen \d_font_scaled_text_face
+\newdimen \d_font_scaled_font_size
+\newconditional\c_font_body_scale
+\newfraction \f_font_body_scale
+
+\unexpanded\def\font_helpers_low_level_define#specification#csname%
+ {% we can now set more at the lua end
+ \glet\somefontname\defaultfontfile
+ \let\somefontsize\empty
+ \clf_definefont_one{\detokenize\expandafter{\normalexpanded{#specification}}}% the escapestring catches at \somedimen
+ % sets \scaledfontmode and \somefontname and \somefontsize
+ \ifcase\fontface\relax
+ % \let\v_font_size_absolute\textface % fontbody
+ \or
+ \let\v_font_size_absolute\textface
+ \or
+ \let\v_font_size_absolute\scriptface
+ \or
+ \let\v_font_size_absolute\scriptscriptface
+ \or
+ \let\v_font_size_absolute\xtextface
+ \or
+ \let\v_font_size_absolute\xxtextface
+ \fi
+ %
+ \ifcase\scaledfontmode\relax
+ % none, avoid the designsize if possible
+ \d_font_scaled_font_size-\plusthousand\scaledpoint
+ \or
+ % at
+ \d_font_scaled_font_size\somefontsize
+ \or
+ % sa
+ \d_font_scaled_font_size\v_font_size_absolute\relax
+ \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size % uses \somefontsize set by lua
+ \or
+ % mo
+ \d_font_scaled_font_size\font_basics_set_mapped_fontsize\v_font_size_absolute
+ \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size
+ \or
+ % scaled, don't use this one as it's unpredictable
+ \d_font_scaled_font_size-\somefontsize\scaledpoint
+ \else % ht cp
+ % experiment, yet undocumented
+ \d_font_scaled_font_size\somefontsize
+ \fi
+ \relax
+ \d_font_scaled_font_size\v_font_size_relative\d_font_scaled_font_size
+ \ifconditional\c_font_auto_size
+ \font_helpers_check_body_scale\fontsize
+ \ifconditional\c_font_body_scale
+ \d_font_scaled_font_size\f_font_body_scale\d_font_scaled_font_size
+ \d_font_scaled_text_face\f_font_body_scale\dimexpr\textface\relax
+ \else
+ \d_font_scaled_font_size\f_font_body_scale
+ \d_font_scaled_text_face\textface
+ \fi
+ \else
+ \d_font_scaled_text_face\textface
+ \fi
+ \edef\somefontspec{at \number\d_font_scaled_font_size sp}%
+ \edef\somefontfile{\truefontname\somefontname}%
+ \ifx\somefontfile\s!unknown
+ \edef\somefontfile{\defaultfontfile}%
+ \fi
+ \font_helpers_update_font_parameters
+ \font_helpers_update_font_class_parameters
+ %\writestatus{fonts}{low level define: #csname/\somefontfile/\number\d_font_scaled_font_size/\fontface/\number\d_font_scaled_text_face}%
+ \clf_definefont_two
+ \ifx\fontclass\empty\s!false\else\s!true\fi
+ {#csname}%
+ {\somefontfile}%
+ \d_font_scaled_font_size
+ \c_font_feature_inheritance_mode
+ {\m_font_class_features}%
+ {\m_font_features}%
+ {\m_font_class_fallbacks}%
+ {\m_font_fallbacks}%
+ \fontface
+ \d_font_scaled_text_face
+ \relativefontid
+ {\m_font_class_goodies}%
+ {\m_font_goodies}%
+ {\m_font_class_designsize}%
+ {\m_font_designsize}%
+ \scaledfontmode
+ \relax
+ \ifcase\scaledfontsize
+ %\scaledfontsize\plusone
+ \let\somefontspec\empty
+ \let\lastrawfontcall\relax
+ \expandafter\let\csname#csname\endcsname\relax
+ \else
+ \edef\somefontspec{at \number\scaledfontsize sp}% we need the resolved designsize (for fallbacks)
+ \expandafter\let\expandafter\lastrawfontcall\csname#csname\endcsname
+ \the\everydefinefont
+ \fi
+ \c_font_feature_inheritance_mode\c_font_feature_inheritance_default}
+
+\def\font_helpers_check_body_scale#fontsize% gets character (x xx a etc)
+ {\ifcsname\??fontenvironments\fontclass\fontbody#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \setfalse\c_font_body_scale % !
+ \orelse\ifcsname\??fontenvironments\fontclass\s!default#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \orelse\ifcsname\??fontenvironments\fontbody#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \setfalse\c_font_body_scale % !
+ \orelse\ifcsname\??fontenvironments\s!default#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \orelse\ifcsname\??fontenvironments\fontclass\s!default\s!text\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \orelse\ifcsname\??fontenvironments\s!default\s!text\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \else
+ \let\f_font_body_scale\plusone
+ \settrue\c_font_body_scale
+ \fi}
+
+%D The following macros are used at the \LUA\ end. Watch the \type {\normal}
+%D hackery: this makes the mkvi parser happy.
+
+% \normaldef\fntsetdefname {\glet\somefontname\defaultfontfile} % do before calling
+% \normaldef\fntsetnopsize {\let\somefontsize\empty} % do before calling
+% \normaldef\fntsetsomename{\normalgdef\somefontname} % takes argument
+% \normaldef\fntsetsomesize{\normaldef\somefontsize} % takes argument
+
+\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue
+
+\tracingfonts\plussix % <id: name @ size>
+
+%D When fontclasses are used, we define the font global, since namespaces are
+%D used. Otherwise we parse the specs each time.
+
+\let\fontfile\s!unknown
+
+%D Relatively new:
+
+\installcorenamespace{fonts}
+\installcorenamespace{fontslanguage}
+
+\installsetuponlycommandhandler \??fonts {fonts}
+
+\newconstant\c_fonts_auto_language
+
+\letvalue{\??fontslanguage\v!auto}\plusone % experimental
+%letvalue{\??fontslanguage\v!yes }\plustwo % less efficient, for experiments
+
+\appendtoks
+ \c_fonts_auto_language
+ \ifcsname\??fontslanguage\fontsparameter\c!language\endcsname
+ \lastnamedcs
+ \else
+ \zerocount
+ \fi
+\to \everysetupfonts
+
+\appendtoks
+ \ifcase\c_fonts_auto_language
+ % nothing
+ \or
+ \addfflanguage
+ % \or
+ % font
+ \fi
+\to \everylanguage
+
+% \setupfonts
+% [\c!language=\v!auto]
+
+%D \macros
+%D {everyfont,everyfontswitch}
+
+\ifdefined\everyfont \else \newtoks\everyfont \fi
+\ifdefined\everyfontswitch \else \newtoks\everyfontswitch \fi
+
+\def\setfontcharacteristics{\the\everyfont}
+
+% \appendtoks
+% \ifcase\c_fonts_auto_language
+% % nothing
+% \or
+% % auto
+% \or
+% \addfflanguage
+% \fi
+% \to \everyfont
+
+%D \macros
+%D {definefont}
+%D
+%D We also accept \type{sa a}||\type{sa d} as specification.
+%D
+%D Before we implement the main definition macro, we first show one for local use:
+%D
+%D \starttyping
+%D \definefont[Some][LucidaBright at 100pt] \Some some
+%D \definefont[More][LucidaBright scaled 3000] \More more
+%D \definefont[Nice][LucidaBright mo 2] \Nice nice
+%D \definefont[Text][LucidaBright sa 5.4] \Text last
+%D \stoptyping
+%D
+%D The implementation looks as follows:
+
+\unexpanded\def\definefont % [name][spec][1.6 | line=10pt | setup_id]
+ {\dotripleempty\font_basics_define_font}
+
+\def\font_basics_define_font
+ {\ifthirdargument
+ \expandafter\font_basics_define_font_a
+ \else
+ \expandafter\font_basics_define_font_b
+ \fi}
+
+\def\font_basics_define_font_a[#name][#specification][#settings]% [name][spec][1.6 | line=10pt | setup_id]
+ {\doifelsesetups{#settings}%
+ {\setuvalue{#name}{\font_basics_define_font_with_setups {#name}{#specification}{#settings}}}
+ {\setuvalue{#name}{\font_basics_define_font_with_parameters{#name}{#specification}{#settings}}}}
+
+\def\font_basics_define_font_b[#name][#specification][#dummy]%
+ {\setuvalue{#name}{\font_basics_define_font_without_parameters{#name}{#specification}}}
+
+\def\font_basics_define_font_with_parameters#name#specification#settings%
+ {\font_basics_define_font_without_parameters{#name}{#specification}%
+ \setuplocalinterlinespace[#settings]%
+ \setupspacing\relax} % is this really needed ?
+
+\def\font_basics_define_font_with_setups#name#specification#settings%
+ {\font_basics_define_font_without_parameters{#name}{#specification}%
+ \setups[#settings]}
+
+%D Beware, in the frozen variants no settings are supported yet, but that might happen
+%D some day.
+
+\unexpanded\def\definefrozenfont
+ {\dotripleempty\font_basics_define_frozen_font}
+
+% \def\font_basics_define_frozen_font[#name][#specification][#settings]%
+% {\begingroup
+% \font_basics_define_font[#name][#specification][#settings]%
+% \csname#name\endcsname
+% \expandafter\expandafter\expandafter\endgroup\expandafter\let\csname#name\endcsname\lastrawfontcall}
+
+\def\font_basics_define_frozen_font[#name][#specification][#settings]%
+ {\begingroup
+ \font_basics_define_font[#name][#specification][#settings]%
+ \csname#name\endcsname
+ \glet\lastglobalrawfontcall\lastrawfontcall
+ \endgroup
+ \expandafter\let\csname#name\endcsname\lastglobalrawfontcall}
+
+%D The instance namespace protection makes the switch local so that we can redefine a
+%D logical name and/or change the size in between.
+
+% todo: now mathsize twice in name (so it can go here)
+% todo: check when mathsize is needed
+
+\ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi
+\ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi
+\ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi
+
+\newconditional\c_font_auto_size \settrue\c_font_auto_size
+
+\let\lastfontidentifier\empty
+
+\def\v_font_identifier_basic{\??fontinstancebasic \lastfontidentifier-\fontsize-\fontface}
+\def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontsize-\fontface}
+
+\let\v_font_identifier_basic_saved\v_font_identifier_basic
+\let\v_font_identifier_class_saved\v_font_identifier_class
+
+% \def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontstyle-\fontsize} % no \fontface
+
+\def\font_basics_define_font_without_parameters#identifier#2%
+ {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \edef\lastfontidentifier{#identifier}%
+ \let\v_font_size_relative\v_font_rscale_default
+ \let\v_font_size_absolute\fontbody
+ \font_helpers_low_level_define{#2}\v_font_identifier_basic
+ \csname\v_font_identifier_basic\endcsname
+ \setfalse\c_font_auto_size
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \let\v_font_identifier_basic\v_font_identifier_basic_saved}
+
+\unexpanded\def\font_helpers_trigger#identifier% make a traced variant
+ {\edef\lastfontidentifier{#identifier}%
+ \ifcsname\v_font_identifier_class\endcsname
+ % \writestatus{fonts}{trigger: reusing \v_font_identifier_class}%
+ \expandafter\font_helpers_trigger_reuse
+ \else
+ % \writestatus{fonts}{trigger: defining \v_font_identifier_class}%
+ \expandafter\font_helpers_trigger_define
+ \fi}
+
+\def\font_helpers_trigger_define#relative#absolute#specification%
+ {\def\v_font_size_relative{#relative}%
+ \def\v_font_size_absolute{#absolute}%
+ \font_helpers_low_level_define{#specification}\v_font_identifier_class
+ \csname\v_font_identifier_class\endcsname
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi
+ \let\v_font_identifier_class\v_font_identifier_class_saved}
+
+\def\font_helpers_trigger_reuse#relative#absolute#specification%
+ {\csname\v_font_identifier_class\endcsname
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi
+ \let\v_font_identifier_class\v_font_identifier_class_saved}
+
+%D \macros
+%D {currentfontbodyscale}
+%D
+%D Sometimes we need to have access to the font scale including the \type {a}||\type
+%D {d} sizes. The next macro returns the current scaling factor. Take a look at
+%D \type {cont-log.tex} for an example of its use.
+
+\installcorenamespace{fontenvironments}
+
+\def\currentfontbodysize % gets number (the normal sa 1 etc)
+ {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
+ \lastnamedcs
+ \else
+ \somefontsize
+ \fi}
+
+\def\currentfontbodyscale % gets character (x xx a etc)
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\fontclass\s!default\fontsize\orelse
+ \ifcsname\??fontenvironments \s!default\fontsize\endcsname \s!default\fontsize\orelse
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \orelse
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else
+ \s!default \fi
+ \endcsname}
+
+\def\font_currentfontbodyscale % gets character (x xx a etc)
+ {\ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments \s!default\fontsize\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else
+ \csname\??fontenvironments \s!default \endcsname \fi}
+
+\def\currentfontscale % used in default definition
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\fontclass\s!default\fontsize\orelse
+ \ifcsname\??fontenvironments \s!default\xfontsize\endcsname \s!default\fontsize\orelse
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \orelse
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else
+ \s!default \fi
+ \endcsname}
+
+\def\font_currentfontscale % used in default definition
+ {\ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments \s!default\xfontsize\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else
+ \csname\??fontenvironments \s!default \endcsname \fi}
+
+\setvalue{\??fontenvironments\s!default}{1}
+
+%D In the following macros we use \type {\currentxfontsize} to hold the current
+%D x||size of the font. This enables us to support for instance \type {\sl} inside a
+%D \type {\tx} switch.
+
+\newconstant\currentxfontsize
+
+\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\s!x\else\s!xx\fi}
+
+%D Now we enter the area of font switching. The switching mechanism has to take care
+%D of several situations, like:
+%D
+%D \startitemize[packed]
+%D \item changing the overal document fonts (including margins, headers and footers)
+%D \item changing local fonts (only the running text)
+%D \item smaller and even more smaller alternatives (super- and subscripts)
+%D \stopitemize
+%D
+%D \TEX\ offers a powerfull family mechanism for super- and subscripts in math mode.
+%D In text mode however, we don't use families for the smaller alternatives, and
+%D therefore have to take care of it otherwise.
+%D
+%D \macros
+%D {definebodyfontenvironment,setupbodyfontenvironment}
+%D
+%D The relationship between the several sizes of a font, is
+%D defined by:
+%D
+%D \showsetup{definebodyfontenvironment}
+%D
+%D Later on we will see how these parameters are used, so for the moment we stick
+%D with an example:
+%D
+%D \starttyping
+%D \definebodyfontenvironment
+%D [12pt]
+%D [ text=12pt,
+%D script=9pt,
+%D scriptscript=7pt,
+%D x=10pt,
+%D xx=8pt,
+%D big=12pt,
+%D small=10pt]
+%D \stoptyping
+%D
+%D The first argument specifies the bodyfont size to which the settings apply. All
+%D second parameters are specified in dimensions and tell us more about related
+%D sizes.
+%D
+%D Afterwards, one can change values with
+%D
+%D \showsetup{setupbodyfontenvironment}
+%D
+%D When instead of a size the keyword \type{unknown} is
+%D passed, fractions (relations) are used instead of fixed
+%D sizes.
+
+%D {\bf Remark:} We need to cover the following cases, otherwise users can get
+%D confused:
+%D
+%D \starttyping
+%D \setupbodyfont[23pt]
+%D
+%D \definebodyfontenvironment[23pt]
+%D \setupbodyfont[23pt]
+%D
+%D \definebodyfontenvironment[23pt]
+%D \definebodyfont[23pt][rm,ss,tt][default]
+%D \setupbodyfont[23pt]
+%D \stoptyping
+%D
+%D Beware: while some font defs can be global, the bodyfont environment checks
+%D local. This means that multiple local checks resulting in definitions are not
+%D that efficient. So, apart from an occasional switch, one should define an
+%D environment at the outer level.
+
+% \definebodyfontenvironment[33pt]
+% \definebodyfontenvironment[dejavu][default][1=.5]
+% \definebodyfontenvironment[dejavu][default][x=1.2]
+% \definebodyfontenvironment[dejavu][default][a=5]
+% \definebodyfontenvironment[dejavu][33pt][x=100pt]
+
+% the lookup order is:
+%
+% [class] [dimension] [parameters]
+% [class] [default] [parameters] % factors
+% [dimension] [parameters]
+% [default] [parameters] % factors
+%
+% with defaults providing factors
+
+% todo: class:size
+% todo: make assignments global
+
+\letvalue\??fontenvironments\empty % so we default to empty
+
+\def\bodyfontvariable#parameter%
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\fontclass\normalizedbodyfontsize#parameter\orelse
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\orelse
+ \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname \normalizedbodyfontsize#parameter\orelse
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi
+ \endcsname}
+
+\def\font_bodyfontvariable#parameter%
+ {\ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi}
+
+\def\bodyfontsizevariable#size#parameter%
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\fontclass#size#parameter\orelse
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\orelse
+ \ifcsname\??fontenvironments #size#parameter\endcsname #size#parameter\orelse
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi
+ \endcsname}
+
+\def\font_bodyfontsizevariable#size#parameter%
+ {\ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments #size#parameter\endcsname\lastnamedcs\orelse
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi}
+
+\def\bodyfontinterlinespace{\bodyfontvariable\c!interlinespace} % used elsewhere
+
+\def\bodyfontdimension#class#size#parameter#body%
+ {\the\dimexpr
+ \ifcsname\??fontenvironments #class#size#parameter\endcsname \lastnamedcs \orelse
+ \ifcsname\??fontenvironments#class\s!default#parameter\endcsname \lastnamedcs\dimexpr#body\relax\orelse % factor
+ \ifcsname\??fontenvironments #size#parameter\endcsname \lastnamedcs \else
+ \lastnamedcs\dimexpr#body\relax\fi % factor
+ \relax}
+
+\unexpanded\def\definebodyfontenvironment
+ {\dotripleempty\font_basics_define_body_font_environment}
+
+\let\setupbodyfontenvironment\definebodyfontenvironment
+
+\installcorenamespace{fontenvironmentknown}
+
+\def\font_helpers_register_environment#class#body%
+ {\expandafter\let\csname\??fontenvironmentknown#class#body\endcsname\empty}
+
+\newmacro\m_font_body
+\newmacro\m_font_body_normalized
+
+\def\font_basics_define_body_font_environment
+ {\ifthirdargument
+ \singleexpandafter\font_basics_define_body_font_environment_class
+ \orelse\ifsecondargument
+ \expandafter\font_basics_define_body_font_environment_empty
+ \else
+ \expandafter\font_basics_define_body_font_environment_unset
+ \fi}
+
+%D First we handle the class specific case. Beware: you can change values before
+%D a bodyfont is loaded but changing them afterwards can be sort of tricky as
+%D values are not consulted afterwards.
+
+\def\processbodyfontenvironmentlist#1% no \unexpanded as then we cannot use it in alignments
+ {\clf_processbodyfontsizes{\strippedcsname#1}}
+
+\def\bodyfontenvironmentlist
+ {\clf_getbodyfontsizes}
+
+\def\font_basics_define_body_font_environment_class[#class][#body][#settings]%
+ {\edef\m_font_body{#body}%
+ \ifx\m_font_body\s!default
+ % these are the last resort within a class
+ \getrawparameters[\??fontenvironments#class\s!default][#settings]%
+ \else
+ \normalizebodyfontsize\m_font_body_normalized\m_font_body
+ \font_basics_define_body_font_environment_size[#class][\m_font_body_normalized][#settings]%
+ \clf_registerbodyfontsize{\m_font_body_normalized}%
+ \fi}
+
+%D The empty case uses the same code but needs to ignore the current class settings
+%D (just to be sure, as it's not really needed).
+
+\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]%
+ {\push_macro_fontclass
+ \let\fontclass\empty
+ \font_basics_define_body_font_environment_class[][#body][#settings]%
+ \pop_macro_fontclass}
+
+\def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]%
+ {\push_macro_fontclass
+ \let\fontclass\empty
+ \font_basics_define_body_font_environment_class[][#body][]%
+ \pop_macro_fontclass}
+
+%D We don't check too soon as we can refer to later definitions.
+
+\newconditional\c_font_defining_environment_state % controls messages
+
+\def\font_basics_define_body_font_environment_size[#class][#normalizedbody][#settings]% normalized body
+ {\getrawparameters[\??fontenvironments#class#normalizedbody][#settings]%
+ \ifcsname\??fontenvironmentknown#class#normalizedbody\endcsname
+ % environment and size already defined
+ \orelse\ifproductionrun
+ \push_macro_fontclass
+ \edef\fontclass{#class}%
+ \font_helpers_register_environment{#class}{#normalizedbody}%
+ \settrue\c_font_defining_environment_state
+ \font_helpers_define_unknown_font{#normalizedbody}% current class
+ \setfalse\c_font_defining_environment_state
+ \pop_macro_fontclass
+ \fi
+ \font_helpers_register_fontbody{#normalizedbody}}
+
+%D Checking
+
+\def\font_helpers_check_bodyfont_environment#normalizedbody#body%
+ {\ifcsname\??fontenvironmentknown\fontclass#normalizedbody\endcsname
+ % already defined
+ \else
+ \font_helpers_check_bodyfont_environment_indeed{#normalizedbody}{#body}%
+ \fi}
+
+\def\font_helpers_check_bodyfont_environment_indeed#normalizedbody#body%
+ {\font_helpers_register_environment\fontclass{#normalizedbody}%
+ \ifcsname\??fontbodyknown#normalizedbody\endcsname
+ \else
+ \font_helpers_define_unknown_font{#normalizedbody}%
+ \fi}
+
+%D We default all parameters to the main bodyfont size, so the next setup is valid
+%D too:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[24pt]
+%D \stoptyping
+%D
+%D All parameters can be redefined when needed, so one doesnot have to stick to the
+%D default ones.
+
+%D \macros
+%D {definebodyfont}
+%D
+%D The next step in defining a bodyfont involves the actual font files, which can be
+%D recognized by their extension \type {tfm}. Installing those file is often beyond
+%D the scope of the user and up to the system administrator.
+%D
+%D \showsetup{definebodyfont}
+%D
+%D This commands takes three arguments: a (series of) bodyfont size(s), the style
+%D group to which the definitions belong, and an alternative, as specified by the
+%D \TEX\ (math) families, extended with~a, b~\unknown.
+%D
+%D We show two examples, that show all the alternative scaling options. The \type
+%D {\tfa} alternatives can be extended with \type {\bfa}, \type {\slb}, etc. or even
+%D \type {e} and higher alternatives. The magic scaled values are derived from plain
+%D \TEX's \type {\magstep}:
+%D
+%D \starttyping
+%D \definebodyfont [12pt] [rm]
+%D [tf=cmr12,
+%D bf=cmbx12,
+%D it=cmti12,
+%D sl=cmsl12,
+%D bi=cmbxti10 at 12pt,
+%D bs=cmbxsl10 at 12pt,
+%D tfa=cmr12 scaled 1.200,
+%D tfb=cmr12 scaled 1.440,
+%D tfc=cmr12 scaled 1.728,
+%D tfd=cmr12 scaled 2.074,
+%D sc=cmcsc10 at 12pt]
+%D
+%D \definebodyfont [12pt,11pt,10pt,9pt,8pt] [rm]
+%D [tf=lbr sa 1,
+%D bf=lbd sa 1,
+%D it=lbi sa 1,
+%D sl=lbsl sa 1,
+%D bi=lbdi sa 1,
+%D bs=lbdi sa 1,
+%D tfa=lbr sa 1.200,
+%D tfb=lbr sa 1.440,
+%D tfc=lbr sa 1.728,
+%D tfd=lbr sa 2.074,
+%D sc=lbr sa 0.833]
+%D \stoptyping
+%D
+%D The second example shows that we can define more sizes at once. The main
+%D difference between these examples is that the Computer Modern Roman come in many
+%D design sizes. This means that there we cannot define them in bulk using \type
+%D {sa}. Instead of \type {rm} (roman) one can define \type {ss} (sans serif), \type
+%D {tt} (teletype), \type {hw} (hand written), \type {cg} (calygraphic) and whatever
+%D styles.
+%D
+%D The first argument may be a comma separated list. This, combined with
+%D specifications using \type{sa} can save a lot of typing. Although all arguments
+%D should be specified, we treat the second argument as optional.
+%D
+%D Defining a bodyfont involves two actions: defining the specific style related
+%D alternatives, like \type {\rma}, \type {\bfa} and \type {\rmsla}, and storing the
+%D definitions of their bodyfont size related fonts. The first step is bodyfont
+%D independant but executed every time. This permits user definitions like \type
+%D {\tfw} or \type {\bfq} for real large alternatives.
+%D
+%D If we move design size info to the lfg file (after all only lm has design sizes)
+%D we can get rid of much code .. 2012 or so.
+
+\installcorenamespace{fontdefinitions}
+
+% [class] [name] [rm,ss] [settings]
+% [class] [10pt,11pt] [rm,ss] [settings]
+% [class] [10pt,11pt] [rm,ss] [name]
+
+% [class] [name] [settings] == [name] [rm] [settings]
+% [class] [10pt,11pt] [settings] == [name] [rm] [settings]
+% [class] [10pt,11pt] [name] == [10pt,11pt] [rm] [name]
+
+\unexpanded\def\definebodyfont
+ {\doquadrupleempty\font_basics_define_body_font}
+
+\def\font_basics_define_body_font[#1][#2][#3][#4]%
+ {\iffourthargument
+ \processcommacommand[#1]{\font_basics_define_body_font_class_given[#2][#3][#4]}%
+ \else
+ \font_basics_define_body_font_class_known[#1][#2][#3]%
+ \fi}
+
+\def\font_basics_define_body_font_class_given[#1][#2][#3]#4%
+ {\push_macro_fontclass
+ \doifelse{#4}\s!default
+ {\let\fontclass\empty}
+ {\def\fontclass{#4}}%
+ \definebodyfont[#1][#2][#3]%
+ \pop_macro_fontclass}
+
+\def\font_basics_define_body_font_class_known
+ {\ifthirdargument
+ \singleexpandafter\font_basics_define_body_font_a
+ \orelse\ifsecondargument
+ \expandafter\font_basics_define_body_font_b
+ \else
+ \expandafter\font_basics_define_body_font_c
+ \fi}
+
+\unexpanded\def\font_basics_define_body_font_b[#whatever][#specification][#dummy]% body|identifier defs|identifier
+ {\font_basics_define_body_font_a[#whatever][\s!rm][#specification]}
+
+\unexpanded\def\font_basics_define_body_font_c[#whatever][#dummya][#dummyb]% body|identifier
+ {\font_basics_define_body_font_a[#whatever][\s!rm][]}
+
+\unexpanded\def\font_basics_define_body_font_a[#whatever]%
+ {\doifelsenumber{#whatever}%
+ \font_basics_define_body_font_body
+ \font_basics_define_body_font_name
+ [#whatever]}
+
+\unexpanded\def\font_basics_define_body_font_body[#body][#style][#specification]%
+ {\ifcondition\validassignment{#specification}%
+ \expandafter\font_basics_define_body_font_body_assignment
+ \else
+ \expandafter\font_basics_define_body_font_body_identifier
+ \fi
+ [#body][#style][#specification]}%
+
+\unexpanded\def\font_basics_define_body_font_name[#name][#style][#specification]%
+ {\ifcondition\validassignment{#specification}%
+ \expandafter\font_basics_define_body_font_name_assignment
+ \else
+ \expandafter\font_basics_define_body_font_name_identifier
+ \fi
+ [#name][#style][#specification]}%
+
+\unexpanded\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]%
+ {\processcommalist[#bodylist]{\font_basics_define_body_font_body_assignment_a{#stylelist}{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body%
+ {\normalizebodyfontsize\m_font_asked_body{#body}%
+ % normally we define quite a lot in advance, i.e global defs
+ \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
+ \processcommalist[#stylelist]{\font_basics_define_body_font_body_assignment_b{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_body_assignment_b#assignments#style%
+ {\edef\m_font_asked_style{#style}%
+ \processcommalist[#assignments]\font_basics_define_body_font_defs}
+
+\unexpanded\def\font_basics_define_body_font_defs
+ {\ifx\fontclass\empty
+ \expandafter\font_basics_define_body_font_defs_nop
+ \else
+ \expandafter\font_basics_define_body_font_defs_yes
+ \fi}
+
+\unexpanded\def\font_basics_define_body_font_defs_yes_normal#assignment%
+ {\ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_yes_mm
+ \else
+ \expandafter\font_basics_define_body_font_yes_xx
+ \fi[#assignment]}
+
+\unexpanded\def\font_basics_define_body_font_defs_nop_normal#assignment%
+ {\ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_nop_mm
+ \else
+ \expandafter\font_basics_define_body_font_nop_xx
+ \fi[#assignment]}
+
+\unexpanded\def\font_basics_define_body_font_defs_yes_traced#assignment%
+ {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
+ \ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_yes_mm
+ \else
+ \expandafter\font_basics_define_body_font_yes_xx
+ \fi[#assignment]}
+
+\unexpanded\def\font_basics_define_body_font_defs_nop_traced#assignment%
+ {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
+ \ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_nop_mm
+ \else
+ \expandafter\font_basics_define_body_font_nop_xx
+ \fi[#assignment]}
+
+\let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_normal
+\let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_normal
+
+\appendtoks
+ \let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_traced
+ \let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_traced
+\to \t_font_tracers_definitions
+
+%D We split into two characters (first part of spec) and the rest: the first two are
+%D the style and the rest is a size, although in practice one will seldom define the
+%D size directly. We might even drop that as it gives faster code.
+
+\unexpanded\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local
+ {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+\unexpanded\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global
+ {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-0}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-4}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-5}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+% \writestatus{fonts}{define \m_asked_style\space yes: {\expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}
+
+%D Here the rest concerns rl or lr so in this case it is not a size specifier but
+%D a directional one.
+
+\unexpanded\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local
+ {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
+ % \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
+ % \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\s!mm-#one#two#rest\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\noexpand\font_rscale_mm}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+% \writestatus{fonts}{define \m_asked_style\space nop: \expandafter\meaning\csname\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
+
+\unexpanded\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global
+ {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
+ % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
+ % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+% \writestatus{fonts}{define \m_asked_style\space yes: \expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
+
+\unexpanded\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]%
+ {\processcommalist[#bodylist]{\font_basics_define_body_font_body_identifier_a{#stylelist}{#name}}}
+
+\unexpanded\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body%
+ {\normalizebodyfontsize\m_font_asked_body{#body}%
+ \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
+ \processcommalist[#stylelist]{\font_basics_define_body_font_body_identifier_b{#name}}}
+
+\unexpanded\def\font_basics_define_body_font_body_identifier_b#name#style%
+ {\edef\m_font_asked_style{#style}%
+ %\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] => [#name]}%
+ \csname\??fontdefinitions#name:\m_font_asked_style\endcsname} % no checking
+
+\unexpanded\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]%
+ {\processcommalist[#stylelist]{\font_basics_define_body_font_name_assignment_a{#name}{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_name_assignment_a#name#assignments#style%
+ {%\writestatus\m!fonts{[#name:#style] => [#assignments]}%
+ \setevalue{\??fontdefinitions#name:#style}{\font_basics_define_body_font_default{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]%
+ {\processcommalist[#stylelist]{\font_basics_define_body_font_name_identifier_a{#name}{#identifier}}}
+
+\unexpanded\def\font_basics_define_body_font_name_identifier_a#name#identifier#style%
+ {%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}%
+ \ifcsname\??fontdefinitions#name:#style\endcsname
+ \expandafter\let\csname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname
+ \else
+ \expandafter\def\csname\??fontdefinitions#name:#style\endcsname{\csname\??fontdefinitions#identifier:#style\endcsname}%
+ \fi}
+
+%D The unknown:
+
+\newconditional\c_font_defining_unknown
+\newconditional\c_font_defining_state
+
+\unexpanded\def\font_helpers_define_unknown_font#body% one level only
+ {\font_helpers_register_fontbody{#body}% prevents loop, can go
+ \setfalse\c_font_defining_state
+ \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_sizes{#body}}%
+ \ifconditional\c_font_defining_state
+ \setfalse\c_font_defining_state
+ \font_helpers_process_style_list{\font_helpers_define_unknown_check_definitions{#body}}%
+ \ifconditional\c_font_defining_state
+ \ifconditional\c_font_defining_environment_state\else
+ %\showmessage\m!fonts{14}{#body}% main
+ \clf_registerunknownbodysize{#body}%
+ \fi
+ \setfalse\c_font_defining_state
+ \font_helpers_register_fontbody{#body}%
+ % needed ?
+ \ifconditional\c_font_defining_unknown
+ \else
+ \settrue\c_font_defining_unknown
+ \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_relatives{#body}}%
+ \setfalse\c_font_defining_unknown
+ \fi
+ \fi
+ \fi}
+
+\def\font_helpers_define_unknown_check_sizes#body#relativesize%
+ {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
+ \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}%
+ \settrue\c_font_defining_state
+ \fi}
+
+\def\font_helpers_define_unknown_check_definitions#body#style%
+ {\ifcsname\??fontdefinitions\s!default:#style\endcsname
+ \edef\m_font_asked_body{#body}%
+ \edef\m_font_asked_style{#style}%
+ \lastnamedcs
+ \settrue\c_font_defining_state
+ \fi}
+
+% \def\font_helpers_define_unknown_check_relatives#body#relativesize%
+% {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else
+% % how \lastnamedcs here
+% \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname
+% \settrue\c_font_defining_state
+% \fi}
+
+\def\font_helpers_define_unknown_check_relatives#body#relativesize%
+ {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else
+ \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname
+ \settrue\c_font_defining_state
+ \fi}
+
+\unexpanded\def\font_basics_define_body_font_default#assignments%
+ {\font_helpers_check_relative_font_size\m_font_asked_style % still needed here?
+ \ifcsname\m_font_asked_style\endcsname\else
+ \normalexpanded{\definefontstyle[\m_font_asked_style][\m_font_asked_style]}%
+ \fi
+ \processcommalist[#assignments]\font_basics_define_body_font_defs
+ \let\p_font_rscale\v_font_rscale_default}
+
+%D These macros show that quite some definitions take place. Fonts are not loaded
+%D yet! This means that at format generation time, no font files are present.
+
+\unexpanded\def\font_basics_switch_points#body%
+ {\ifcsname\??fontbodyknown#body\endcsname \else
+ % we need to check the relative sizes for this body
+ \font_helpers_define_unknown_font{#body}%
+ \fi%
+ \ifcsname\??fontbodyknown#body\endcsname % always true now
+ \font_basics_complete_switch{#body}%
+ \localbodyfontsize#body\relax
+ \normalizebodyfontsize\normalizedbodyfontsize\localbodyfontsize
+ \font_helpers_check_bodyfont_environment\normalizedbodyfontsize\normalizedbodyfontsize % !!
+ \else
+ \showmessage\m!fonts4{#body}%
+ \fi}
+
+\unexpanded\def\font_basics_switch_style#style%
+ {\ifcsname\??fontstyle#style\endcsname
+ \lastnamedcs
+ \edef\fontstyle{#style}%
+ \ifmmode\mr\fi % in order to be compatible with \rm in math mode
+ % \the\everybodyfont % cleaner, in setting size as well as style
+ \else
+ \showmessage\m!fonts5{#style}%
+ \fi}
+
+%D Here comes the main font switching macros. These macros handle changes in size as
+%D well as returning to the global bodyfont size.
+
+\ifdefined\font_preloads_at_definition \else \let\font_preloads_at_definition\relax \fi
+
+\def\font_helpers_set_font#method#specification%
+ {\edef\m_font_specification{#specification}%
+ \ifx\m_font_specification\empty \else
+ \ifx\m_font_specification\v!global % we can have all kind of presets
+ \restoreglobalbodyfont
+ \else
+ \processcommacommand[\m_font_specification]{\font_helpers_set_font_check_size}%
+ \processcommacommand[\m_font_specification]{\font_helpers_set_font_set_font{#method}}%
+ \ifproductionrun
+ \font_preloads_at_definition
+ \font_basics_switch_points\normalizedbodyfontsize
+ \font_basics_switch_style\fontstyle
+ \ifx\defaultfontclass\empty
+ \let\defaultfontclass\fontclass
+ \fi
+ \fi
+ \fi
+ \currentxfontsize\zerocount
+ \fi}
+
+\def\font_helpers_set_font_check_size#option%
+ {\doifelsenumber{#option}{\font_helpers_check_bodyfont_environment{#option}{#option}}\donothing}
+
+\def\font_helpers_set_font_set_font#method#option% method=1: set, method=2: switch
+ {\doifsomething{#option}{\font_helpers_set_font_set_font_option{#method}{#option}}}
+
+\def\font_helpers_set_font_set_font_option#method#option%
+ {\doifelsenumber{#option}%
+ \font_helpers_set_font_set_font_option_body
+ \font_helpers_set_font_set_font_option_keyword
+ {#method}{#option}{#option}}
+
+\newmacro\m_font_keyword
+
+\unexpanded\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message%
+ {\edef\m_font_keyword{#keyword}%
+ \ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname
+ \edef\m_font_step{\font_bodyfontvariable\m_font_keyword}%
+ \normalexpanded{\font_helpers_set_font_set_font_option_body{#method}{\m_font_step}{#message}}%
+ \orelse\ifx\m_font_keyword\v!reset
+ \let\fontstyle\empty % new 31/7/2006
+ \let\fontsize \empty
+ \orelse\ifcsname\??fontstyle\m_font_keyword\endcsname
+ \let\fontstyle\m_font_keyword
+ \else
+ \setcurrentfontclass\m_font_keyword
+ \ifcase#method\relax
+ \let\globalfontclass\globalfontclass % -)
+ \else
+ \let\globalfontclass\fontclass
+ \fi
+ \font_helpers_set_fontstyle_of_fontclass
+ \fi}
+
+\def\font_helpers_set_fontstyle_of_fontclass % will be overloaded later
+ {\let\fontstyle\s!rm}
+
+\unexpanded\def\font_helpers_set_font_set_font_option_body#method#body#message%
+ {\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls
+ \ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else
+ \font_helpers_define_unknown_font\normalizedsetfont
+ \fi
+ \ifcsname\??fontbodyknown\normalizedsetfont\endcsname
+ \localbodyfontsize\normalizedsetfont
+ \let\normalizedbodyfontsize\normalizedsetfont
+ \else
+ \showmessage\m!fonts4{#message}%
+ %\font_helpers_set_font_set_font_option_body_fallbacks{#method}{#body}%
+ \fi}
+
+% we need to check the fontclass
+
+\def\registerfontclass#class%
+ {\letgvalue{\??fontclassyes#class}\v!yes} % global ?
+
+\def\setcurrentfontclass#class%
+ {\ifcsname\??fontclassyes#class\endcsname
+ \edef\fontclass{#class}%
+ \orelse\ifcsname\??fontclassnop#class\endcsname
+ % already tried
+ \else % too messy: \ifcase\currentgrouplevel % (unpredictable)
+ \trycurrentfontclass{#class}%
+ \fi}
+
+\ifdefined\trycurrentfontclass \else
+
+ \unexpanded\def\trycurrentfontclass#typeface%
+ {\letvalueempty{\??fontclassnop#typeface}}
+
+\fi
+
+\let\defaultfontstyle \s!rm
+\let\defaultfontalternative\s!tf
+\let\defaultfontsize \empty
+\let\defaultfontface \!!zerocount
+
+%D So far for synchronisation. (We can inline the following macros.)
+
+\unexpanded\def\setcurrentfont#body#style#alternative#size% not used
+ {\edef\fontbody {#body}%
+ \edef\fontstyle {#style}%
+ \edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\setcurrentfontbody#body% % not used
+ {\edef\fontbody{#body}%
+ \font_helpers_synchronize_font}
+
+% For Taco: optional fall backs:
+
+\ifdefined\font_typescripts_inherit_check \else
+ \let\font_typescripts_inherit_check\gobbleoneargument % implemented in type-ini
+\fi
+
+\unexpanded\def\font_helpers_set_current_font_style#style%
+ {\edef\fontstyle{#style}%
+ \font_typescripts_inherit_check\fontstyle
+ \ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_xsize_alternative#xsize#alternative%
+ {\edef\fontface{#xsize}%
+ \edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_alternative#alternative%
+ {\edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_size#size%
+ {\edef\fontsize{#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl
+ {\edef\fontstyle {#style}%
+ \edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_style_size#style#size% \rma
+ {\edef\fontstyle{#style}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla
+ {\edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla
+ {\edef\fontstyle {#style}%
+ \edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy
+ {\ifx\fontclass\empty
+ \applyfontstrategies
+ \else
+ \applyfontclassstrategies
+ \fi
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+%D This is the resolver for special cases (sizes) and in practice it is not called
+%D that often so further optimization makes no sense.
+
+\def\font_helpers_check_strategy_class_a % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_b
+ \fi}
+
+\def\font_helpers_check_strategy_class_b % --- --- --- def % pt tt bf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_c
+ \fi}
+
+\def\font_helpers_check_strategy_class_c % --- --- def --- % pt tt tf a
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_d
+ \fi}
+
+\def\font_helpers_check_strategy_class_d % --- --- def def % pt tt tf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_e
+ \fi}
+
+\def\font_helpers_check_strategy_class_e % --- def def def % pt rm tf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_f
+ \fi}
+
+\def\font_helpers_check_strategy_class_f % def def def def % rm tf
+ {\ifcsname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_a
+ \fi}
+
+% no class
+
+\def\font_helpers_check_strategy_a % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_b
+ \fi}
+
+\def\font_helpers_check_strategy_b % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_c
+ \fi}
+
+\def\font_helpers_check_strategy_c % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_d
+ \fi}
+
+\def\font_helpers_check_strategy_d % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_e
+ \fi}
+
+\def\font_helpers_check_strategy_e % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_f
+ \fi}
+
+\def\font_helpers_check_strategy_f % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \fi}
+
+\let\applyfontstrategies \font_helpers_check_strategy_a
+\let\applyfontclassstrategies\font_helpers_check_strategy_class_a
+
+%D Let's synchronize:
+
+\newconditional\c_font_synchronize \settrue\c_font_synchronize
+
+\prependtoks
+ \ifconditional\c_font_synchronize
+ \font_helpers_synchronize_math
+ \font_helpers_synchronize_font % problem: syncs last font
+ \fi
+\to \everybodyfont
+
+%D Setting the normal sizes as well as the x and xx smaller sizes is accomplished by
+%D the next set of macros. When in math mode, the commands \type {\tx} and \type
+%D {\txx} are just a switch to the script and double script styles, but in text mode
+%D the values defined by the bodyfontenvironment are used. Here we also set \type
+%D {\currentxfontsize}.
+
+\def\font_helpers_set_current_font_xxx_alternative#alternative#xsize#scriptstyle%
+ {\ifmmode
+ #scriptstyle%
+ \else
+ \font_helpers_set_current_xsize_alternative{#xsize}{#alternative}%
+ \fi}
+
+\def\font_helpers_reset_x_fontsize
+ {\ifcase\currentxfontsize\else
+ \currentxfontsize\zerocount
+ % also \sx and \sxx ?
+ \let\tx \normaltx
+ \let\txx\normaltxx
+ \fi}
+
+\let\font_helpers_check_nested_x_fontsize\relax
+
+\def\font_helpers_set_current_font_x_alternative#alternative%
+ {\font_helpers_check_nested_x_fontsize
+ \font_helpers_set_current_font_xxx_alternative{#alternative}{4}\scriptstyle
+ \currentxfontsize\plusone
+ \let\tx\txx}
+
+\def\font_helpers_set_current_font_xx_alternative#alternative%
+ {\font_helpers_check_nested_x_fontsize
+ \font_helpers_set_current_font_xxx_alternative{#alternative}{5}\scriptscriptstyle
+ \currentxfontsize\plustwo
+ \let\tx\empty
+ \let\txx\empty}
+
+%D This alterative is not really needed, but for old time's sake we keep it there.
+%D We can speed it up when needed.
+
+\def\font_helpers_set_current_font_x_style_alternative #alternative{\csname#alternative\endcsname\tx}
+\def\font_helpers_set_current_font_xx_style_alternative#alternative{\csname#alternative\endcsname\txx}
+
+%D These macros also show us that when we call for \type {\tx}, this macro is
+%D redefined to be \type {\txx}. Therefore calls like:
+%D
+%D \startbuffer
+%D {small \tx is \tx beautiful}
+%D {small \tx is \txx beautiful}
+%D {small \txx is \tx beautiful}
+%D {small \txx is \txx beautiful}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D result in:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D Setting the main size involves the style list and therefore takes a bit more
+%D time. Keep in mind that the fontsize is represented by a character or empty.
+
+\installcorenamespace{fontscalex}
+\installcorenamespace{fontscalexx}
+
+\newconditional\c_font_inherit_scale
+
+\def\font_scale_inherit#1%
+ {\begingroup
+ \scratchcounterone\fontid\font\relax
+ \currentxfontsize\plusone
+ \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}%
+ \scratchcountertwo\fontid\font\relax
+ \currentxfontsize\plustwo
+ \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}%
+ \scratchcounterthree\fontid\font\relax
+ % parent -> x -> xx
+ % parent -> xx
+ \global\expandafter\chardef\csname\??fontscalex \number\scratchcounterone\endcsname\scratchcountertwo
+ \global\expandafter\chardef\csname\??fontscalexx\number\scratchcounterone\endcsname\scratchcounterthree
+ \global\expandafter\chardef\csname\??fontscalex \number\scratchcountertwo\endcsname\scratchcounterthree
+ \global\expandafter\chardef\csname\??fontscalexx\number\scratchcountertwo\endcsname\scratchcounterthree
+ \endgroup
+ \setfontid\csname#1\number\fontid\font\endcsname}
+
+\def\font_scale_inherit_x
+ {\ifcsname\??fontscalex\number\fontid\font\endcsname
+ \setfontid\lastnamedcs
+ \else
+ \font_scale_inherit\??fontscalex
+ \fi
+ \ifskipfontcharacteristics
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+\def\font_scale_inherit_xx
+ {\ifcsname\??fontscalexx\number\fontid\font\endcsname
+ \setfontid\lastnamedcs
+ \else
+ \font_scale_inherit\??fontscalexx
+ \fi
+ \ifskipfontcharacteristics
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+\def\font_scale_defined_x
+ {\let\fontface\!!plusfour
+ \let\fontalternative\fontalternative
+ \font_helpers_synchronize_font}
+
+\def\font_scale_defined_xx
+ {\let\fontface\!!plusfive
+ \let\fontalternative\fontalternative
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\tx
+ {\currentxfontsize\plusone
+ \ifmmode
+ \scriptstyle
+ \else\ifconditional\c_font_inherit_scale
+ \font_scale_inherit_x
+ \else
+ \font_scale_defined_x
+ \fi\fi
+ \let\tx\txx}
+
+\unexpanded\def\txx
+ {\currentxfontsize\plustwo
+ \ifmmode
+ \scriptscriptstyle
+ \else\ifconditional\c_font_inherit_scale
+ \font_scale_inherit_xx
+ \else
+ \font_scale_defined_xx
+ \fi\fi
+ \let\tx \empty
+ \let\txx\empty}
+
+\unexpanded\def\sx
+ {\currentxfontsize\plusone
+ \ifmmode
+ \scriptstyle
+ \else
+ \font_scale_inherit_x
+ \fi
+ \let\tx\txx
+ \let\sx\sxx}
+
+\unexpanded\def\sxx
+ {\currentxfontsize\plustwo
+ \ifmmode
+ \scriptscriptstyle
+ \else
+ \font_scale_inherit_xx
+ \fi
+ \let\tx \empty
+ \let\txx\empty
+ \let\sx \empty
+ \let\sxx\empty}
+
+\unexpanded\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me
+\unexpanded\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me
+
+\let\normaltx \tx
+\let\normaltxx\txx
+
+\let\normalsx \sx
+\let\normalsxx\sxx
+
+%D When asking for a complete font switch, for instance from 10 to 12~points, the
+%D next macro does the job. First we normalize the size, next we define the current
+%D range of text, script and scriptscript sizes, then we set the text fonts and the
+%D math families and finally we activate the default typeface and also set the font
+%D specific parameters assigned to \type {\everybodyfont}.
+
+\def\textface {\currentbodyfontdimension\s!text }
+\def\scriptface {\currentbodyfontdimension\s!script }
+\def\scriptscriptface{\currentbodyfontdimension\s!scriptscript}
+\def\xtextface {\currentbodyfontdimension\s!x }
+\def\xxtextface {\currentbodyfontdimension\s!xx }
+
+\installcorenamespace{fontbodyfaces}
+
+\unexpanded\def\font_basics_complete_switch#size%
+ {\bodyfontsize#size\relax
+ \normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize
+ \expandafter\let\expandafter\font_basics_set_faces\csname\??fontbodyfaces\fontbody\endcsname
+ \ifx\font_basics_set_faces\relax
+ \font_basics_set_faces_preset
+ \fi
+ \font_basics_set_faces}
+
+\def\font_basics_set_faces_preset
+ {\edef\font_basics_set_faces{% 0.2 sec on 10K \tfa
+ \noexpand\edef\noexpand\textface {\currentbodyfontdimension\s!text }%
+ \noexpand\edef\noexpand\scriptface {\currentbodyfontdimension\s!script }%
+ \noexpand\edef\noexpand\scriptscriptface{\currentbodyfontdimension\s!scriptscript}%
+ \noexpand\edef\noexpand\xtextface {\currentbodyfontdimension\s!x }%
+ \noexpand\edef\noexpand\xxtextface {\currentbodyfontdimension\s!xx }%
+ }%
+ \expandafter\glet\csname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces}
+
+\def\currentbodyfontdimension#parameter% there can be factors here
+ {\the\dimexpr
+ \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??fontenvironments\fontclass\s!default#parameter\endcsname
+ \lastnamedcs
+ \dimexpr\normalizedbodyfontsize\relax
+ \orelse\ifcsname\??fontenvironments\normalizedbodyfontsize#parameter\endcsname
+ \lastnamedcs
+ \else
+ \csname\??fontenvironments\s!default#parameter\endcsname
+ \dimexpr\normalizedbodyfontsize\relax
+ \fi
+ \relax}
+
+%D \macros
+%D {setupbodyfont,switchtobodyfont}
+%D
+%D The next two macros are user ones. With \type {\setupbodyfont} one can set the
+%D document bodyfont size, font family, style and/or options defined in files, for
+%D example:
+%D
+%D \starttyping
+%D \setupbodyfont[modern,12pt,roman]
+%D \stoptyping
+%D
+%D This command affects the document as a whole: text, headers and footers. The
+%D second macro however affects only the text:
+%D
+%D \starttyping
+%D \switchtobodyfont[10pt]
+%D \stoptyping
+%D
+%D So we've got:
+%D
+%D \showsetup{setupbodyfont}
+%D \showsetup{switchtobodyfont}
+%D
+%D Both macros look alike. The second one also has to take all kind of keywords into
+%D account.
+
+\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi
+\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi
+
+% \newtoks \everysetupbodyfont
+% \newtoks \everyswitchtobodyfont
+
+\unexpanded\def\setupbodyfont
+ {\doifelsenextoptionalcs\font_basics_setupbodyfont_yes\font_basics_setupbodyfont_nop}
+
+\def\font_basics_setupbodyfont_nop
+ {\restoreglobalbodyfont
+ \saveinterlinespace}
+
+\def\font_basics_setupbodyfont_yes[#specification]%
+ {\doifsomething{#specification}
+ {\font_helpers_set_font\plusone{#specification}%
+ \globalbodyfontsize\localbodyfontsize
+ \normalizebodyfontsize\normalizedglobalbodyfontsize\globalbodyfontsize
+ \let\globalfontstyle\fontstyle
+ \ifproductionrun
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace
+ \fi
+ \the\everysetupbodyfont}}
+
+\unexpanded\def\font_basics_switchtobodyfont#specification%
+ {\edef\m_font_step{\font_bodyfontvariable{#specification}}%
+ \ifx\m_font_step\empty
+ \font_helpers_set_font\zerocount{#specification}%
+ \else
+ \font_helpers_switch_bodyfont_step % so we have a fast [small] switch
+ \fi
+ \the\everybodyfont
+ \the\everyswitchtobodyfont}
+
+\unexpanded\def\switchtobodyfont[#specification]% could become an ifx
+ {\doifsomething{#specification}{\font_basics_switchtobodyfont{#specification}}}
+
+\unexpanded\def\usebodyfontparameter#1%
+ {\edef\m_font_bodyfont_asked{#1\c!bodyfont}%
+ \ifx\m_font_bodyfont_asked\empty\else
+ \font_basics_switchtobodyfont\m_font_bodyfont_asked
+ \fi}
+
+\def\font_helpers_switch_bodyfont_step
+ {\font_basics_switch_points\m_font_step
+ \font_basics_switch_style \fontstyle}
+
+%D The following alternative is meant for math||to||text switching and will be
+%D optimized.
+
+\unexpanded\def\fastswitchtobodyfont#name%
+ {\ifcsname\??fontenvironments\normalizedbodyfontsize#name\endcsname
+ %\edef\futurebodyfontsize{\csname\??fontenvironments\normalizedbodyfontsize#name\endcsname}%
+ \edef\futurebodyfontsize{\lastnamedcs}%
+ \ifcsname\??fontbodyknown\futurebodyfontsize\endcsname
+ \font_basics_complete_switch\futurebodyfontsize
+ \localbodyfontsize\futurebodyfontsize\relax
+ \fi
+ \fi
+ \csname\??fontstyle\fontstyle\endcsname
+ \the\everybodyfont}
+
+%D \starttyping
+%D $\cases{& \ccaron}$ $x=\hbox{\ccaron $x=\hbox{\ccaron}$}$
+%D \stoptyping
+
+%D \macros
+%D {usebodyfont}
+%D
+%D This looks nicer then a switch in the preamble
+%D
+%D \starttyping
+%D \usebodyfont[pagella,10pt]
+%D \usebodyfont[termes,10pt]
+%D \usebodyfont[dejavu,10pt]
+%D
+%D \setupbodyfont[dejavu]
+%D
+%D \starttext
+%D test
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\usebodyfont[#1]%
+ {\ifx\fontclass\empty
+ \setupbodyfont[#1]%
+ \else
+ \switchtobodyfont[#1]%
+ \fullrestoreglobalbodyfont
+ \fi}
+
+\unexpanded\def\showbodyfontstate
+ {\dontleavehmode
+ \start
+ \infofont
+ [fontclass: \fontclass,\space
+ fontbody: \fontbody ,\space
+ fontface: \fontface ,\space
+ fontsize: \fontsize ]%
+ \stop}
+
+%D Handy for manuals:
+
+%D The \type {\tochar} commmand takes a specification:
+%D
+%D \starttabulate[|l|l|l|]
+%D \NC e \NC entity \NC e:eacute \NC \NR
+%D \NC x \NC hexadecimal unicode \NC x:013D \NC \NR
+%D \NC d \NC decimal unicode \NC d:123 \NC \NR
+%D \NC s \NC hexadecimal index (slot) \NC s:210D \NC \NR
+%D \NC i \NC decimal index \NC i:456 \NC \NR
+%D \NC n \NC name \NC n:eight \NC \NR
+%D \NC c \NC name \NC c:x \NC \NR
+%D \NC u \NC unicode descriptions \NC u:dog \NC \NR
+%D \NC a \NC all (also descriptions) \NC a:rewind \NC \NR
+%D \stoptabulate
+%D
+%D This is an expandable command!
+
+\unexpanded\def\fontchar #character{\clf_fontchar{#character}}
+\unexpanded\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax}
+ \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef)
+
+%D The next auxilliary macro is an alternative to \type {\fontname}.
+
+\def\purefontname#font{\clf_purefontname{\fontname#font}}
+
+%D \macros
+%D {switchstyleonly}
+%D
+%D For switching a style but keeping the alternative, there
+%D is:
+%D
+%D \starttyping
+%D {\bf text \switchstyleonly\ss text}
+%D {\bf text \switchstyleonly[ss]text}
+%D {\sl text \switchstyleonly[sansserif]text}
+%D \stoptyping
+
+\unexpanded\def\switchstyleonly
+ {\doifelsenextoptionalcs\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg}
+
+\def\font_basics_switch_style_only_arg#name% stupid version
+ {\font_helpers_set_current_font_style{\csname\??fontshortstyle\checkedstrippedcsname#name\endcsname}%
+ \the\everybodyfont} % needed ?
+
+\def\font_basics_switch_style_only_opt[#name]% todo : check
+ {\font_helpers_set_current_font_style{\csname\??fontshortstyle#name\endcsname}%
+ \the\everybodyfont} % needed ?
+
+%D \macros
+%D {definebodyfontswitch}
+%D
+%D \PLAIN\ \TEX\ defines some macro's like \type {\tenpoint} to switch to a specific
+%D bodyfontsize. Just for the sake of compatibility we can define them like:
+%D
+%D \starttyping
+%D \definebodyfontswitch [twelvepoint] [12pt]
+%D \stoptyping
+%D
+%D We don't support language specific synonyms here.
+
+\unexpanded\def\definebodyfontswitch
+ {\dodoubleargument\font_basics_define_bodyfont_switch}
+
+\def\font_basics_define_bodyfont_switch[#command][#specification]% no longer a commalist (not useful)
+ {\setvalue{#command}{\switchtobodyfont[#specification]}}%
+
+%D \macros
+%D {setsmallbodyfont,setmainbodyfont,setbigbodyfont}
+%D
+%D When we're typesetting at for instance 10pt, we can call for the \type {small} as
+%D well as the \type {big} alternative, related to this main size, using \type
+%D {\switchtobodyfont[small]}. The three alternatives can be activated by the next
+%D three system calls and are defined by the bodyfontenvironment.
+
+\newmacro\m_font_step
+
+\def\font_helpers_set_bodyfont_step#step%
+ {\edef\m_font_step{\font_bodyfontvariable{#step}}% not always \cs
+ \font_basics_switch_points\m_font_step
+ \font_basics_switch_style \fontstyle}
+
+\unexpanded\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont}
+\unexpanded\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont}
+
+\unexpanded\def\setmainbodyfont
+ {\font_basics_switch_points\normalizedbodyfontsize
+ \font_basics_switch_style\fontstyle
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+%D \macros
+%D {restoreglobalbodyfont}
+%D
+%D Users can set whatever font available while typesetting text. Pagenumbers,
+%D footers, headers etc. however must be typeset in the main bodyfont and style of
+%D the document. Returning to the global state can be done with the next macro:
+%D
+%D This macro has to be called when entering the pagebody handling routine as well
+%D as the footnote insert routine. Users can access this feature |<|for instance
+%D when one wants to typeset tables and alike in the main bodyfont and style while
+%D the running text is temporary set to a smaller one|>| by saying \type
+%D {\switchtobodyfont [global]}.
+
+\let\globalfontstyle\s!rm
+
+\unexpanded\def\fullrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \let\fontface\defaultfontface
+ \currentxfontsize\zerocount
+ \let\fontclass\globalfontclass
+ \font_basics_switch_points\normalizedglobalbodyfontsize
+ \font_basics_switch_style\globalfontstyle
+ \redoconvertfont % just in case a pagebreak occurs
+ \tf
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+\unexpanded\def\partialrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \let\fontface\defaultfontface
+ \currentxfontsize\zerocount
+ \redoconvertfont
+ \tf
+ \the\everybodyfont % indeed needed
+ \the\everyglobalbodyfont % indeed needed
+ \saveinterlinespace}
+
+\unexpanded\def\restoreglobalbodyfont % ook style etc
+ {\ifx\fontclass\globalfontclass
+ \ifx\fontstyle\globalfontstyle
+ \ifx\normalizedbodyfontsize\normalizedglobalbodyfontsize
+ \partialrestoreglobalbodyfont
+ \else
+ \fullrestoreglobalbodyfont
+ \fi
+ \else
+ \fullrestoreglobalbodyfont
+ \fi
+ \else
+ \fullrestoreglobalbodyfont
+ \fi}
+
+% in case of troubles: \let\restorebodyfont\fullrestoreglobalbodyfont
+
+%D Here are some fast variants that can be used in cases where no font system is
+%D needed and where fonts are frozen:
+%D
+%D \starttyping
+%D \definefont [TestA][Serif at 10pt]
+%D \predefinefont[TestB][Serif at 20pt]
+%D
+%D \testfeatureonce{1000}{{\TestA}} % .312
+%D \testfeatureonce{1000}{{\TestB}} % < .016
+%D \testfeatureonce{1000}{{\definedfont[Serif at 30pt]}} % .312
+%D \testfeatureonce{1000}{{\predefinedfont[Serif at 40pt]}} % < .016
+%D \stoptyping
+
+\installcorenamespace{predefinedfont}
+
+\unexpanded\def\predefinefont[#1]#2[#3]% global !
+ {\setugvalue{#1}{\font_basics_predefine{#1}{#3}}}
+
+\unexpanded\def\predefinedfont[#1]% global !
+ {\ifcsname\??predefinedfont#1\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_predefined{#1}%
+ \fi}
+
+\unexpanded\def\font_basics_predefine#1#2%
+ {\font_basics_defined_font_yes[#2]%
+ \expandafter\glet\csname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname}
+
+\unexpanded\def\font_basics_predefined#1%
+ {\font_basics_predefine{\??predefinedfont#1}{#1}}
+
+%D Handy helper:
+
+\unexpanded\def\savedefinedfont[#1]%
+ {\bgroup
+ \definedfont[#1]%
+ \xdef\saveddefinedfontid {\number\fontid\font}%
+ \xdef\saveddefinedfontname{\fontname\font}%
+ \egroup}
+
+\def\saveddefinedfontid {\number\fontid\font}
+\def\saveddefinedfontname{\fontname\font}
+
+%D Ugly helper:
+
+\unexpanded\def\saverunningstyleandcolor
+ {\unexpanded\edef\restorerunningstyleandcolor
+ {\setfontid \number\fontid\font
+ \attribute\colormodelattribute \the\attribute\colormodelattribute
+ \attribute\colorattribute \the\attribute\colorattribute
+ \attribute\transparencyattribute\the\attribute\transparencyattribute
+ \relax}}
+
+\let\restorerunningstyleandcolor\relax
+
+%D Handy for defining additional glyphs:
+
+\let\getprivateglyphslot\clf_getprivateglyphslot % kind of private macro
+
+\let\getprivatechar \clf_getprivatechar % gives back a utf !
+\let\getprivatemathchar \clf_getprivatemathchar % gives back a utf !
+\let\getprivateslot \clf_getprivateslot % companion to fonts.helpers.addprivate
+
+% \unexpanded\def\getprivatemathchar#1%
+% {\begingroup\the\textfont\zerocount\getprivatechar{#1}\endgroup}
+
+\def\privatechar % the text variant gets expanded to utf
+ {\ifmmode
+ \expandafter\getprivatemathchar
+ \else
+ \expandafter\getprivatechar
+ \fi}
+
+%D Some fonts can have color specifiers:
+%D
+%D \starttyping
+%D \definefontfeature[seguiemj-cl][default][colr=yes,ccmp=yes,dist=yes]
+%D \definefontsynonym[emoji][seguiemj*seguiemj-cl]
+%D
+%D \definecolor[emoji-red] [r=.4]
+%D \definecolor[emoji-gray][s=1,t=.5,a=1]
+%D
+%D %definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] % bad
+%D \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] % okay
+%D
+%D \definefontfeature[seguiemj-r][ccmp=yes,dist=yes,colr=emoji-r]
+%D
+%D \definefont[MyEmojiR][seguiemj*seguiemj-r @ 100pt]
+%D
+%D \startTEXpage[offset=10pt]
+%D \MyEmojiR\resolvedemoji{triangular ruler}
+%D \stopTEXpage
+%D \stoptyping
+
+\unexpanded\def\definefontcolorpalette
+ {\dodoubleargument\font_define_color_palette}
+
+\def\font_define_color_palette[#1][#2]%
+ {\clf_definefontcolorpalette{#1}{#2}}
+
+%D \macros
+%D {addfontpath}
+%D
+%D A way to add a path at runtime (no need to generate database):
+
+\unexpanded\def\usefontpath[#1]%
+ {\clf_addfontpath{#1}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-ini.mkvi b/tex/context/base/mkiv/font-ini.mkvi
index 0f29cf155..99e7117a3 100644
--- a/tex/context/base/mkiv/font-ini.mkvi
+++ b/tex/context/base/mkiv/font-ini.mkvi
@@ -53,8 +53,8 @@
\unprotect
-%D There are several ways to specify a font. Three of them are
-%D pure \TeX\ ones, the fourth one is new:
+%D There are several ways to specify a font. Three of them are pure \TEX\ ones, the
+%D fourth one is new:
%D
%D \starttyping
%D \font\name=cmr12
@@ -63,18 +63,15 @@
%D \font\name=cmr12 sa 1.440
%D \stoptyping
%D
-%D The non||\TEX\ alternative \type{sa} stands for {\em scaled
-%D at}. This means as much as: scale the bodyfontsize with this
-%D factor. The scaled option is not that useful as one needs to
-%D know the design size.
+%D The non||\TEX\ alternative \type{sa} stands for {\em scaled at}. This means as
+%D much as: scale the bodyfontsize with this factor. The scaled option is not that
+%D useful as one needs to know the design size.
%D
-%D Because \type {sa} (scaled at) and \type {mo} (mapped on)
-%D are not low level \TEX\ supported alternatives, we have to
-%D test for it ourselves. In doing so, we need an auxiliary
-%D \DIMENSION. We cannot use \type{\scratchdimen} because font
-%D loading can happen at any moment due to postponed loading.
-%D We could instead have used dirty grouping tricks, but this
-%D one works too.
+%D Because \type {sa} (scaled at) and \type {mo} (mapped on) are not low level \TEX\
+%D supported alternatives, we have to test for it ourselves. In doing so, we need an
+%D auxiliary \DIMENSION. We cannot use \type{\scratchdimen} because font loading can
+%D happen at any moment due to postponed loading. We could instead have used dirty
+%D grouping tricks, but this one works too.
% \enableexperiments[fonts.autorscale]
%
@@ -101,9 +98,8 @@
%D \macros
%D {rm,ss,tt,hw,cg}
%D
-%D Fonts are defined in separate files. When we define a font,
-%D we distinguish between several styles. In most cases we will
-%D use:
+%D Fonts are defined in separate files. When we define a font, we distinguish
+%D between several styles. In most cases we will use:
%D
%D \startlinecorrection
%D \starttable[|l||]
@@ -115,8 +111,8 @@
%D \stoptable
%D \stoplinecorrection
%D
-%D The number of styles is not limited to these three. When
-%D using Lucida Bright we can for instance also define:
+%D The number of styles is not limited to these three. When using Lucida Bright we
+%D can for instance also define:
%D
%D \startlinecorrection
%D \starttable[|l||]
@@ -127,8 +123,8 @@
%D \stoptable
%D \stoplinecorrection
%D
-%D Within such a font set (\type{cmr}) and style (\type{\rm})
-%D we can define a number of text font alternatives:
+%D Within such a font set (\type{cmr}) and style (\type{\rm}) we can define a number
+%D of text font alternatives:
%D
%D \startlinecorrection
%D \starttable[|l||]
@@ -145,12 +141,11 @@
%D \stoplinecorrection
%D
%D Internally fonts are stored as combination of size, style
-%D and alternative, e.g. \type{12pt}+\type{\ss}+\type{\bf}.
-%D Users are not confronted with sizes, but use the style or
-%D style+alternative to activate them.
+%D and alternative, e.g. \type{12pt}+\type{\ss}+\type{\bf}. Users are not confronted
+%D with sizes, but use the style or style+alternative to activate them.
%D
-%D During the definition of a bodyfont one can also declare the
-%D available larger alternatives:
+%D During the definition of a bodyfont one can also declare the available larger
+%D alternatives:
%D
%D \starttyping
%D \tf \tfa \tfb \tfc ...
@@ -167,13 +162,12 @@
%D \slx \slxx
%D \stoptyping
%D
-%D There are only two smaller alternatives per style. The
-%D larger alternatives on the other hand have no limitations.
+%D There are only two smaller alternatives per style. The larger alternatives on the
+%D other hand have no limitations.
%D
-%D These larger alternatives are mostly used in chapter and
-%D section titles or on title pages. When one switches to a
-%D larger alternative, the bold an other ones automatically
-%D adapt themselves:
+%D These larger alternatives are mostly used in chapter and section titles or on
+%D title pages. When one switches to a larger alternative, the bold an other ones
+%D automatically adapt themselves:
%D
%D \startbuffer
%D \tfd Hi \bf there\sl, here \tfb I \bf am
@@ -189,8 +183,8 @@
%D \getbuffer
%D \stopexample
%D
-%D Maybe this mechanism isn't always as logic, but as said
-%D before, we tried to make it as intuitive as possible.
+%D Maybe this mechanism isn't always as logic, but as said before, we tried to make
+%D it as intuitive as possible.
%D
%D So a specific kind of glyph can be characterized by:
%D
@@ -200,52 +194,43 @@
%D
%D The last component (the size) is optional.
%D
-%D We introduced \type{\tf} as command to call for the current
-%D normally sized typeface. This commands results in roman,
-%D sans serif, teletype or whatever style is in charge. Such
-%D rather massive switches of style sometimes take more
-%D processing time than comfortable. Of course there is a
-%D workaround for this: we can call fonts directly by means of
-%D commands like:
+%D We introduced \type {\tf} as command to call for the current normally sized
+%D typeface. This commands results in roman, sans serif, teletype or whatever style
+%D is in charge. Such rather massive switches of style sometimes take more
+%D processing time than comfortable. Of course there is a workaround for this: we
+%D can call fonts directly by means of commands like:
%D
%D \starttyping
%D \rmtf \sssl \tttf \rmbsa
%D \stoptyping
%D
-%D One should realize that this fast calls have limitations,
-%D they lack for instance automatic super- and subscript
-%D support.
-%D
-%D This leaves us two more commands: \type{\tx} and
-%D \type{\txx}. These activate a smaller and even more smaller
-%D font than the current one and adapt themselves to the
-%D current alternative, so when \type{\bf} is active,
-%D \type{\tx} gives a smaller boldface, which in turn can be
-%D called directly by \type{\bfx}.
-%D
-%D These two smaller alternatives are specified by the bodyfont
-%D environment and therefore not necessarily have similar sizes
-%D as \type{\scriptsize} and \type{\scriptscriptsize}. The main
-%D reason for this incompatibility (which can easily be undone)
-%D lays in the fact that we often want a bit bigger characters
-%D than in math mode. In \CONTEXT\ for instance the \type{\tx}
-%D and \type{\txx} commands are used for surrogate
-%D \cap{smallcaps} which support both nesting and alternatives,
-%D like in {\bf\cap{a \cap{small} world}}, which was typeset by
+%D One should realize that this fast calls have limitations, they lack for instance
+%D automatic super- and subscript support.
+%D
+%D This leaves us two more commands: \type {\tx} and \type {\txx}. These activate a
+%D smaller and even more smaller font than the current one and adapt themselves to
+%D the current alternative, so when \type {\bf} is active, \type {\tx} gives a
+%D smaller boldface, which in turn can be called directly by \type {\bfx}.
+%D
+%D These two smaller alternatives are specified by the bodyfont environment and
+%D therefore not necessarily have similar sizes as \type {\scriptsize} and \type
+%D {\scriptscriptsize}. The main reason for this incompatibility (which can easily
+%D be undone) lays in the fact that we often want a bit bigger characters than in
+%D math mode. In \CONTEXT\ for instance the \type {\tx} and \type {\txx} commands
+%D are used for surrogate \cap {smallcaps} which support both nesting and
+%D alternatives, like in {\bf \cap {a \cap {small} world}}, which was typeset by
%D
%D \starttyping
%D \bf\cap{a \cap{small} world}
%D \stoptyping
%D
-%D And compare $\rm \scriptstyle THIS$ with the slightly larger
-%D \cap{THIS}: \ruledhbox{$\rm \scriptstyle scriptstyle: THIS$}
-%D or \ruledhbox{\cap{x style: THIS}} makes a big difference.
+%D And compare $\rm \scriptstyle THIS$ with the slightly larger \cap {THIS}:
+%D \ruledhbox {$\rm \scriptstyle scriptstyle: THIS$} or \ruledhbox {\cap {x style:
+%D THIS}} makes a big difference.
%D
-%D The \type{x..d} sizes should be used grouped. If you
-%D don't group them, i.e. call them in a row, \CONTEXT\ will
-%D not be able to sort out your intention (\type {x} inside
-%D \type {d} inside \type {x}. etc.). The following table
-%D demonstrates this:
+%D The \type {x..d} sizes should be used grouped. If you don't group them, i.e. call
+%D them in a row, \CONTEXT\ will not be able to sort out your intention (\type {x}
+%D inside \type {d} inside \type {x}. etc.). The following table demonstrates this:
%D
%D \def\FontState{\setstrut\ruledhbox{\strut Hello}}
%D
@@ -398,10 +383,9 @@
%D \macros
%D {everybodyfont,everyglobalbodyfont}
%D
-%D Every change in bodyfont size has conseqences for the baseline
-%D distance and skips between paragraphs. These are initialized
-%D in other modules. Here we only provide the hooks that
-%D garantees their handling.
+%D Every change in bodyfont size has conseqences for the baseline distance and skips
+%D between paragraphs. These are initialized in other modules. Here we only provide
+%D the hooks that garantees their handling.
%D
%D At the system level one can initialize thing like:
%D
@@ -411,20 +395,19 @@
%D \macros
%D {globalbodyfontsize,localbodyfontsize,bodyfontsize}
-
-%D Here we have to distinguish between the global (overal) bodyfont
-%D size and the local (sometimes in the textflow) size. We store
-%D these dimensions in two \DIMENSION\ registers. These registers are
-%D not to be misused in calculations.
+%D
+%D Here we have to distinguish between the global (overal) bodyfont size and the
+%D local (sometimes in the textflow) size. We store these dimensions in two
+%D \DIMENSION\ registers. These registers are not to be misused in calculations.
\ifdefined\globalbodyfontsize\else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
\ifdefined\localbodyfontsize \else \newdimen\localbodyfontsize \fi \localbodyfontsize =\globalbodyfontsize
\ifdefined\bodyfontsize \else \newdimen\bodyfontsize \fi \bodyfontsize =\globalbodyfontsize
-%D When we assign for instance 12pt to a \DIMENSION\ register the \type
-%D {\the}'d value comes out as 12.0pt, which is often not the way users
-%D specify the bodyfont size. Therefore we use normalized values. They
-%D are cached to save overhead in \LUA\ calls.
+%D When we assign for instance 12pt to a \DIMENSION\ register the \type {\the}'d
+%D value comes out as 12.0pt, which is often not the way users specify the bodyfont
+%D size. Therefore we use normalized values. They are cached to save overhead in
+%D \LUA\ calls.
% \setnewconstant\fontdigits\plustwo % from now on always 2
@@ -465,11 +448,10 @@
%D \macros
%D {mapfontsize}
%D
-%D For special purposes, like in math, you may want to use
-%D slightly different sizes than the ones given. This happens
-%D for instance with the Math Times fonts. Mapped font sizes
-%D can be specified by using the \type {mo} key instead of
-%D \type {sa} in font definitions.
+%D For special purposes, like in math, you may want to use slightly different sizes
+%D than the ones given. This happens for instance with the Math Times fonts. Mapped
+%D font sizes can be specified by using the \type {mo} key instead of \type {sa} in
+%D font definitions.
%D
%D \startbuffer
%D \mapfontsize[10pt][11pt]
@@ -558,10 +540,9 @@
%D \macros
%D {definefontstyle,definefontsize,definefontalternative}
%D
-%D When setting of switching the overall style we can use the
-%D short identifier like rm and ss, but when defined we can
-%D also use more verbose names like roman or sansserif. Such
-%D names are defined by:
+%D When setting of switching the overall style we can use the short identifier like
+%D rm and ss, but when defined we can also use more verbose names like roman or
+%D sansserif. Such names are defined by:
%D
%D \starttyping
%D \definefontstyle [serif,rm] [rm]
@@ -633,12 +614,12 @@
\definefontstyle [\s!ss] [\s!ss]
\definefontstyle [\s!tt] [\s!tt]
-%D We define all the font switching commands globally. After all they are part
-%D of the formal font interface once defined. The size can be empty (so
-%D checking is needed as \type {\bf} is already defined)
-
-%D The \type {\normal..} variants are available as extras for cases where
-%D the \type {..} is overloaded.
+%D We define all the font switching commands globally. After all they are part of
+%D the formal font interface once defined. The size can be empty (so checking is
+%D needed as \type {\bf} is already defined).
+%D
+%D The \type {\normal..} variants are available as extras for cases where the \type
+%D {..} is overloaded.
\newmacro\m_font_mm
@@ -724,23 +705,20 @@
%D Scaling macros:
%D
-%D This system is somewhat complicated by two (possible conflicting)
-%D demands:
+%D This system is somewhat complicated by two (possible conflicting) demands:
%D
%D \startitemize
-%D \item We support wildcards like \type {sa *} which will adapt
-%D to the current size. This is also the default specification.
-%D \item We support named scales like \type {sa d}; beware: \type
-%D {x} and \type {xx} are valid scales but they are not alway
-%D the same as the ones used in for instance \type {\bfx} because
-%D there the sized come from the bodyfont environment. In the
-%D future there maybe a switch that also honors the environment
-%D in named scales.
+%D \item We support wildcards like \type {sa *} which will adapt to the current
+%D size. This is also the default specification.
+%D \item We support named scales like \type {sa d}; beware: \type {x} and \type {xx}
+%D are valid scales but they are not alway the same as the ones used in for
+%D instance \type {\bfx} because there the sized come from the bodyfont
+%D environment. In the future there maybe a switch that also honors the
+%D environment in named scales.
%D \stopitemize
%D
-%D Keep in mind that the smaller sizes are just for text super and
-%D subscripts while larger sizes can be used in titles where for
-%D instance math follows the size.
+%D Keep in mind that the smaller sizes are just for text super and subscripts while
+%D larger sizes can be used in titles where for instance math follows the size.
% b:x{\definedfont[SerifBold sa b]x}{\bfb x $x^x$}\par
% 1:x{\definedfont[SerifBold sa 1]x}{\bf x $x^x$}\par
@@ -993,8 +971,7 @@
%D
%D We also accept \type{sa a}||\type{sa d} as specification.
%D
-%D Before we implement the main definition macro, we first show
-%D one for local use:
+%D Before we implement the main definition macro, we first show one for local use:
%D
%D \starttyping
%D \definefont[Some][LucidaBright at 100pt] \Some some
@@ -1120,9 +1097,8 @@
%D \macros
%D {currentfontbodyscale}
%D
-%D Sometimes we need to have access to the font scale
-%D including the \type{a}||\type{d} sizes. The next macro
-%D returns the current scaling factor. Take a look at
+%D Sometimes we need to have access to the font scale including the \type {a}||\type
+%D {d} sizes. The next macro returns the current scaling factor. Take a look at
%D \type {cont-log.tex} for an example of its use.
\installcorenamespace{fontenvironments}
@@ -1192,30 +1168,27 @@
\setvalue{\??fontenvironments\s!default}{1}
-%D In the following macros we use \type{\currentxfontsize} to
-%D hold the current x||size of the font. This enables us to
-%D support for instance \type{\sl} inside a \type{\tx} switch.
+%D In the following macros we use \type {\currentxfontsize} to hold the current
+%D x||size of the font. This enables us to support for instance \type {\sl} inside a
+%D \type {\tx} switch.
\newconstant\currentxfontsize
\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\s!x\else\s!xx\fi}
-%D Now we enter the area of font switching. The switching
-%D mechanism has to take care of several situations, like:
+%D Now we enter the area of font switching. The switching mechanism has to take care
+%D of several situations, like:
%D
%D \startitemize[packed]
-%D \item changing the overal document fonts (including margins,
-%D headers and footers)
-%D \item changing local fonts (only the running text)
-%D \item smaller and even more smaller alternatives (super-
-%D and subscripts)
+%D \item changing the overal document fonts (including margins, headers and footers)
+%D \item changing local fonts (only the running text)
+%D \item smaller and even more smaller alternatives (super- and subscripts)
%D \stopitemize
%D
-%D \TEX\ offers a powerfull family mechanism for super- and
-%D subscripts in math mode. In text mode however, we don't use
-%D families for the smaller alternatives, and therefore have
-%D to take care of it otherwise.
-
+%D \TEX\ offers a powerfull family mechanism for super- and subscripts in math mode.
+%D In text mode however, we don't use families for the smaller alternatives, and
+%D therefore have to take care of it otherwise.
+%D
%D \macros
%D {definebodyfontenvironment,setupbodyfontenvironment}
%D
@@ -1224,8 +1197,8 @@
%D
%D \showsetup{definebodyfontenvironment}
%D
-%D Later on we will see how these parameters are used, so for
-%D the moment we stick with an example:
+%D Later on we will see how these parameters are used, so for the moment we stick
+%D with an example:
%D
%D \starttyping
%D \definebodyfontenvironment
@@ -1239,9 +1212,9 @@
%D small=10pt]
%D \stoptyping
%D
-%D The first argument specifies the bodyfont size to which the
-%D settings apply. All second parameters are specified in
-%D dimensions and tell us more about related sizes.
+%D The first argument specifies the bodyfont size to which the settings apply. All
+%D second parameters are specified in dimensions and tell us more about related
+%D sizes.
%D
%D Afterwards, one can change values with
%D
@@ -1251,8 +1224,8 @@
%D passed, fractions (relations) are used instead of fixed
%D sizes.
-%D {\bf Remark:} We need to cover the following cases, otherwise users can
-%D get confused:
+%D {\bf Remark:} We need to cover the following cases, otherwise users can get
+%D confused:
%D
%D \starttyping
%D \setupbodyfont[23pt]
@@ -1265,10 +1238,9 @@
%D \setupbodyfont[23pt]
%D \stoptyping
%D
-%D Beware: while some font defs can be global, the bodyfont
-%D environment checks local. This means that multiple local
-%D checks resulting in definitions are not that efficient.
-%D So, apart from an occasional switch, one should define an
+%D Beware: while some font defs can be global, the bodyfont environment checks
+%D local. This means that multiple local checks resulting in definitions are not
+%D that efficient. So, apart from an occasional switch, one should define an
%D environment at the outer level.
% \definebodyfontenvironment[33pt]
@@ -1383,8 +1355,8 @@
\clf_registerbodyfontsize{\m_font_body_normalized}%
\fi}
-%D The empty case uses the same code but needs to ignore the current class
-%D settings (just to be sure, as it's not really needed).
+%D The empty case uses the same code but needs to ignore the current class settings
+%D (just to be sure, as it's not really needed).
\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]%
{\push_macro_fontclass
@@ -1433,36 +1405,33 @@
\font_helpers_define_unknown_font{#normalizedbody}%
\fi}
-%D We default all parameters to the main bodyfont size, so the next
-%D setup is valid too:
+%D We default all parameters to the main bodyfont size, so the next setup is valid
+%D too:
%D
%D \starttyping
%D \definebodyfontenvironment[24pt]
%D \stoptyping
%D
-%D All parameters can be redefined when needed, so one doesnot have to
-%D stick to the default ones.
+%D All parameters can be redefined when needed, so one doesnot have to stick to the
+%D default ones.
%D \macros
%D {definebodyfont}
%D
-%D The next step in defining a bodyfont involves the actual font
-%D files, which can be recognized by their extension
-%D \type{tfm}. Installing those file is often beyond the
-%D scope of the user and up to the system administrator.
+%D The next step in defining a bodyfont involves the actual font files, which can be
+%D recognized by their extension \type {tfm}. Installing those file is often beyond
+%D the scope of the user and up to the system administrator.
%D
%D \showsetup{definebodyfont}
%D
-%D This commands takes three arguments: a (series of) bodyfont
-%D size(s), the style group to which the definitions belong,
-%D and an alternative, as specified by the \TEX\ (math) families,
-%D extended with~a, b~\unknown.
+%D This commands takes three arguments: a (series of) bodyfont size(s), the style
+%D group to which the definitions belong, and an alternative, as specified by the
+%D \TEX\ (math) families, extended with~a, b~\unknown.
%D
-%D We show two examples, that show all the alternative
-%D scaling options. The \type{\tfa} alternatives can be
-%D extended with \type{\bfa}, \type{\slb}, etc. or even
-%D \type{e} and higher alternatives. The magic scaled
-%D values are derived from plain \TEX's \type {\magstep}:
+%D We show two examples, that show all the alternative scaling options. The \type
+%D {\tfa} alternatives can be extended with \type {\bfa}, \type {\slb}, etc. or even
+%D \type {e} and higher alternatives. The magic scaled values are derived from plain
+%D \TEX's \type {\magstep}:
%D
%D \starttyping
%D \definebodyfont [12pt] [rm]
@@ -1492,29 +1461,25 @@
%D sc=lbr sa 0.833]
%D \stoptyping
%D
-%D The second example shows that we can define more sizes at
-%D once. The main difference between these examples is that the
-%D Computer Modern Roman come in many design sizes. This means
-%D that there we cannot define them in bulk using \type{sa}.
-%D Instead of \type{rm} (roman) one can define \type{ss} (sans
-%D serif), \type{tt} (teletype), \type{hw} (hand written),
-%D \type{cg} (calygraphic) and whatever styles.
-%D
-%D The first argument may be a comma separated list. This,
-%D combined with specifications using \type{sa} can save a lot
-%D of typing. Although all arguments should be specified, we
-%D treat the second argument as optional.
-%D
-%D Defining a bodyfont involves two actions: defining the
-%D specific style related alternatives, like \type{\rma},
-%D \type{\bfa} and \type{\rmsla}, and storing the definitions
-%D of their bodyfont size related fonts. The first step is
-%D bodyfont independant but executed every time. This permits
-%D user definitions like \type{\tfw} or \type{\bfq} for real
-%D large alternatives.
-
-%D If we move design size info to the lfg file (after all only lm
-%D has design sizes) we can get rid of much code .. 2012 or so.
+%D The second example shows that we can define more sizes at once. The main
+%D difference between these examples is that the Computer Modern Roman come in many
+%D design sizes. This means that there we cannot define them in bulk using \type
+%D {sa}. Instead of \type {rm} (roman) one can define \type {ss} (sans serif), \type
+%D {tt} (teletype), \type {hw} (hand written), \type {cg} (calygraphic) and whatever
+%D styles.
+%D
+%D The first argument may be a comma separated list. This, combined with
+%D specifications using \type{sa} can save a lot of typing. Although all arguments
+%D should be specified, we treat the second argument as optional.
+%D
+%D Defining a bodyfont involves two actions: defining the specific style related
+%D alternatives, like \type {\rma}, \type {\bfa} and \type {\rmsla}, and storing the
+%D definitions of their bodyfont size related fonts. The first step is bodyfont
+%D independant but executed every time. This permits user definitions like \type
+%D {\tfw} or \type {\bfq} for real large alternatives.
+%D
+%D If we move design size info to the lfg file (after all only lm has design sizes)
+%D we can get rid of much code .. 2012 or so.
\installcorenamespace{fontdefinitions}
@@ -1651,9 +1616,9 @@
\let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_traced
\to \t_font_tracers_definitions
-% We split into two characters (first part of spec) and the rest: the first two are the style and
-% the rest is a size, although in practice one will seldom define the size directly. We might even
-% drop that as it gives faster code.
+%D We split into two characters (first part of spec) and the rest: the first two are
+%D the style and the rest is a size, although in practice one will seldom define the
+%D size directly. We might even drop that as it gives faster code.
\unexpanded\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local
{\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
@@ -1844,9 +1809,8 @@
\showmessage\m!fonts5{#style}%
\fi}
-%D Here comes the main font switching macros. These macros
-%D handle changes in size as well as returning to the global
-%D bodyfont size.
+%D Here comes the main font switching macros. These macros handle changes in size as
+%D well as returning to the global bodyfont size.
\ifdefined\font_preloads_at_definition \else \let\font_preloads_at_definition\relax \fi
@@ -2022,8 +1986,8 @@
\the\everyfontswitch
\fi}
-%D This is the resolver for special cases (sizes) and in practice it is not called that often
-%D so further optimization makes no sense.
+%D This is the resolver for special cases (sizes) and in practice it is not called
+%D that often so further optimization makes no sense.
\def\font_helpers_check_strategy_class_a % --- --- --- --- % pt tt bf a
{\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
@@ -2135,12 +2099,11 @@
\fi
\to \everybodyfont
-%D Setting the normal sizes as well as the x and xx smaller
-%D sizes is accomplished by the next set of macros. When in
-%D math mode, the commands \type{\tx} and \type{\txx} are
-%D just a switch to the script and double script styles, but
-%D in text mode the values defined by the bodyfontenvironment are
-%D used. Here we also set \type{\currentxfontsize}.
+%D Setting the normal sizes as well as the x and xx smaller sizes is accomplished by
+%D the next set of macros. When in math mode, the commands \type {\tx} and \type
+%D {\txx} are just a switch to the script and double script styles, but in text mode
+%D the values defined by the bodyfontenvironment are used. Here we also set \type
+%D {\currentxfontsize}.
\def\font_helpers_set_current_font_xxx_alternative#alternative#xsize#scriptstyle%
{\ifmmode
@@ -2181,15 +2144,14 @@
\let\tx\empty
\let\txx\empty}
-% This alterative is not really needed, but for old time's sake
-% we keep it there. We can speed it up when needed.
+%D This alterative is not really needed, but for old time's sake we keep it there.
+%D We can speed it up when needed.
\def\font_helpers_set_current_font_x_style_alternative #alternative{\csname#alternative\endcsname\tx}
\def\font_helpers_set_current_font_xx_style_alternative#alternative{\csname#alternative\endcsname\txx}
-%D These macros also show us that when we call for \type{\tx},
-%D this macro is redefined to be \type{\txx}. Therefore calls
-%D like:
+%D These macros also show us that when we call for \type {\tx}, this macro is
+%D redefined to be \type {\txx}. Therefore calls like:
%D
%D \startbuffer
%D {small \tx is \tx beautiful}
@@ -2206,9 +2168,8 @@
%D \getbuffer
%D \stoplines
%D
-%D Setting the main size involves the style list and therefore
-%D takes a bit more time. Keep in mind that the fontsize is
-%D represented by a character or empty.
+%D Setting the main size involves the style list and therefore takes a bit more
+%D time. Keep in mind that the fontsize is represented by a character or empty.
% \unexpanded\def\tx {\font_helpers_set_current_font_x_alternative \fontalternative}
% \unexpanded\def\txx{\font_helpers_set_current_font_xx_alternative\fontalternative}
@@ -2343,13 +2304,11 @@
\let\normalsx \sx
\let\normalsxx\sxx
-%D When asking for a complete font switch, for instance from 10
-%D to 12~points, the next macro does the job. First we
-%D normalize the size, next we define the current range of
-%D text, script and scriptscript sizes, then we set the text
-%D fonts and the math families and finally we activate the
-%D default typeface and also set the font specific parameters
-%D assigned to \type{\everybodyfont}
+%D When asking for a complete font switch, for instance from 10 to 12~points, the
+%D next macro does the job. First we normalize the size, next we define the current
+%D range of text, script and scriptscript sizes, then we set the text fonts and the
+%D math families and finally we activate the default typeface and also set the font
+%D specific parameters assigned to \type {\everybodyfont}.
\def\textface {\currentbodyfontdimension\s!text }
\def\scriptface {\currentbodyfontdimension\s!script }
@@ -2416,16 +2375,16 @@
%D \macros
%D {setupbodyfont,switchtobodyfont}
%D
-%D The next two macros are user ones. With \type{\setupbodyfont}
-%D one can set the document bodyfont size, font family, style
-%D and/or options defined in files, for example:
+%D The next two macros are user ones. With \type {\setupbodyfont} one can set the
+%D document bodyfont size, font family, style and/or options defined in files, for
+%D example:
%D
%D \starttyping
%D \setupbodyfont[modern,12pt,roman]
%D \stoptyping
%D
-%D This command affects the document as a whole: text, headers
-%D and footers. The second macro however affects only the text:
+%D This command affects the document as a whole: text, headers and footers. The
+%D second macro however affects only the text:
%D
%D \starttyping
%D \switchtobodyfont[10pt]
@@ -2436,8 +2395,8 @@
%D \showsetup{setupbodyfont}
%D \showsetup{switchtobodyfont}
%D
-%D Both macros look alike. The second one also has to take
-%D all kind of keywords into account.
+%D Both macros look alike. The second one also has to take all kind of keywords into
+%D account.
\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi
\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi
@@ -2488,8 +2447,8 @@
{\font_basics_switch_points\m_font_step
\font_basics_switch_style \fontstyle}
-%D The following alternative is meant for math||to||text
-%D switching and will be optimized.
+%D The following alternative is meant for math||to||text switching and will be
+%D optimized.
\unexpanded\def\fastswitchtobodyfont#name%
{\ifcsname\??fontenvironments\normalizedbodyfontsize#name\endcsname
@@ -2608,9 +2567,8 @@
%D \macros
%D {definebodyfontswitch}
%D
-%D \PLAIN\ \TEX\ defines some macro's like \type{\tenpoint}
-%D to switch to a specific bodyfontsize. Just for the sake of
-%D compatibility we can define them like:
+%D \PLAIN\ \TEX\ defines some macro's like \type {\tenpoint} to switch to a specific
+%D bodyfontsize. Just for the sake of compatibility we can define them like:
%D
%D \starttyping
%D \definebodyfontswitch [twelvepoint] [12pt]
@@ -2627,11 +2585,10 @@
%D \macros
%D {setsmallbodyfont,setmainbodyfont,setbigbodyfont}
%D
-%D When we're typesetting at for instance 10pt, we can call for
-%D the \type{small} as well as the \type{big} alternative,
-%D related to this main size, using \type{\switchtobodyfont[small]}.
-%D The three alternatives can be activated by the next three
-%D system calls and are defined by the bodyfontenvironment.
+%D When we're typesetting at for instance 10pt, we can call for the \type {small} as
+%D well as the \type {big} alternative, related to this main size, using \type
+%D {\switchtobodyfont[small]}. The three alternatives can be activated by the next
+%D three system calls and are defined by the bodyfontenvironment.
\newmacro\m_font_step
@@ -2653,17 +2610,15 @@
%D \macros
%D {restoreglobalbodyfont}
%D
-%D Users can set whatever font available while typesetting text.
-%D Pagenumbers, footers, headers etc. however must be typeset
-%D in the main bodyfont and style of the document. Returning to
-%D the global state can be done with the next macro:
+%D Users can set whatever font available while typesetting text. Pagenumbers,
+%D footers, headers etc. however must be typeset in the main bodyfont and style of
+%D the document. Returning to the global state can be done with the next macro:
%D
-%D This macro has to be called when entering the pagebody
-%D handling routine as well as the footnote insert routine.
-%D Users can access this feature |<|for instance when one wants
-%D to typeset tables and alike in the main bodyfont and style
-%D while the running text is temporary set to a smaller one|>|
-%D by saying \type{\switchtobodyfont[global]}.
+%D This macro has to be called when entering the pagebody handling routine as well
+%D as the footnote insert routine. Users can access this feature |<|for instance
+%D when one wants to typeset tables and alike in the main bodyfont and style while
+%D the running text is temporary set to a smaller one|>| by saying \type
+%D {\switchtobodyfont [global]}.
\let\globalfontstyle\s!rm
@@ -2709,8 +2664,8 @@
% in case of troubles: \let\restorebodyfont\fullrestoreglobalbodyfont
-%D Here are some fast variants that can be used in cases where no font
-%D system is needed and where fonts are frozen:
+%D Here are some fast variants that can be used in cases where no font system is
+%D needed and where fonts are frozen:
%D
%D \starttyping
%D \definefont [TestA][Serif at 10pt]
diff --git a/tex/context/base/mkiv/font-mat.mklx b/tex/context/base/mkiv/font-mat.mklx
new file mode 100644
index 000000000..d08a2ce87
--- /dev/null
+++ b/tex/context/base/mkiv/font-mat.mklx
@@ -0,0 +1,500 @@
+%D \module
+%D [ file=font-mat,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Math,
+%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.
+
+\writestatus{loading}{ConTeXt Font Macros / Math}
+
+\unprotect
+
+%D Be nice:
+
+\ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi
+\ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi
+\ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi
+
+%D The order 3 2 1 of siuze matters: needed for math-fbk relative size storage!
+
+%D \macros
+%D {textonly}
+%D
+%D Traditionally math has a big impact on font definitions, mainly because we need
+%D to define alphabet variants using families and fonts. This means that one can
+%D easily get 10 fonts loaded per math size. In \MKIV\ we use a different approach:
+%D one family which has either a virtual font made of traditional fonts, or an
+%D \OPENTYPE\ font that has it all.
+%D
+%D We currently use only one math family but in the future we might consider using a
+%D second one for bold math. For the moment we keep the \MKII\ method of using a
+%D token register for definitions but we already dropped the text and symbols ones
+%D since they now live in the same family.
+
+\newtoks \t_font_math_strategies
+\newconditional\c_font_synchronize_math_fonts \settrue\c_font_synchronize_math_fonts
+
+\unexpanded\def\font_helpers_synchronize_math % math stuff in mmode
+ {\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi}
+
+\unexpanded\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this
+
+%D The main math font definer. We have removed some optimized code simply because we
+%D now always have a fontclass. We could check for fontclass being default or empty
+%D and save a few tests but it does not help us when no math is defined.
+%D
+%D Because we want to keep mr=.. and mb=... settings (read: not break downward
+%D compatibility by enforcing mrlr etc) we need a bit more code that optimal.
+
+% todo: \c_font_fam_mr
+
+\let\c_font_fam_mr \zerocount % math regular
+\let\c_font_fam_mr_lr\plusone % math regular l2r
+\let\c_font_fam_mr_rl\plustwo % math regular r2l
+
+\let\c_font_fam_mb \plusthree % math bold
+\let\c_font_fam_mb_lr\plusfour % math bold l2r
+\let\c_font_fam_mb_rl\plusfive % math bold r2l
+
+\definesystemattribute[mathfamily][public]
+
+\newconditional\c_font_bidirectional_mathstrategy % can be default, not that much overhead: \settrue\c_font_bidirectional_mathstrategy
+\newconditional\c_font_complete_bold_mathstrategy \settrue\c_font_complete_bold_mathstrategy
+
+\def\mathtextsuffix {-text}
+\def\mathscriptsuffix {-script}
+\def\mathscriptscriptsuffix{-scriptscript}
+
+\def\mathsizesuffix{\ifcase\fontface\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi}
+
+%D Beware: truefontname also does a fallback on defaultfontclass so there
+%D can be some interference here, which is why we use a different method
+%D for bold.
+
+\def\font_helpers_set_math_family_a
+ {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs \orelse
+ \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs \else
+ \font_helpers_set_math_family_b
+ \fi}
+
+\def\font_helpers_set_math_family_b
+ {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs \orelse
+ \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs \else
+ \font_helpers_set_math_family_c
+ \fi}
+
+\def\font_helpers_set_math_family_c
+ {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs \orelse
+ \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs \else
+ \settrue \c_font_auto_size
+ \fi}
+
+\let\mathsizesuffix\empty
+
+\def\font_helpers_set_math_family_indeed#mrtag#family% \fontface etc are also used later on
+ {\let\savedfontbody\fontbody
+ \let\fontfamily#family%
+ % the order is important as we depend on known id's when completing fonts
+ % enabling is needed when we have fallbacks which spoils the families
+ \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree
+ \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % defines
+ \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % enables
+ \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo
+ \font_helpers_set_math_family_a\scriptfont #mrtag\font % defines
+ \font_helpers_set_math_family_a\scriptfont #mrtag\font % enables
+ \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone
+ \font_helpers_set_math_family_a\textfont #mrtag\font % defines
+ \font_helpers_set_math_family_a\textfont #mrtag\font % enables
+ \let\mathsizesuffix\empty \let\fontface\!!zerocount
+ \let\fontbody\savedfontbody
+ \setfalse\c_font_auto_size}
+
+\def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs #font#mbfam\font \orelse
+ \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs #font#mbfam\font \else
+ #font#mbfam#font#mrfam%
+ \fi}
+
+\def\font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam% \c_font_fam_mb \s!mb \c_font_fam_mr
+ {\let\savedfontclass\defaultfontclass
+ \let\defaultfontclass\fontclass % else truefontname falls back on the wrong one
+ \let\savedfontbody\fontbody
+ \let\fontfamily#familytag%
+ \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree
+ \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% defines
+ \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% enables
+ \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo
+ \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% defines
+ \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% enables
+ \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone
+ \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% defines
+ \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% enables
+ \let\mathsizesuffix\empty \let\fontface\!!zerocount
+ \let\fontbody\savedfontbody
+ \let\defaultfontclass\savedfontclass
+ \setfalse\c_font_auto_size}
+
+% optimized: math fonts are never changed (10K \bfa $x$: 3.2 => 2.5 (baseline 1.0))
+%
+% sort of tricky: we cannot reset in \everybeforedefinetypeface as we don't know
+% all sizes so we postpone the optimization to the first starttext
+%
+% pitfall: we should reset 'm when a fontclass name is reused
+
+\newconditional\optimizemathfontdefinitions \settrue\optimizemathfontdefinitions
+
+\def\font_helpers_set_math_family#mrfam#familytag%
+ {\ifconditional\optimizemathfontdefinitions
+ \ifcsname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
+ % \writestatus{fonts}{math: reusing \fontclass\fontbody\s!mm#familytag\fontsize1}%
+ \font_helpers_preset_math_family_indeed#mrfam#familytag%
+ \else
+ % \writestatus{fonts}{math: defining \fontclass\fontbody\s!mm#familytag\fontsize1}%
+ \font_helpers_set_math_family_indeed#mrfam#familytag%
+ \fi
+ \else
+ \font_helpers_set_math_family_indeed#mrfam#familytag%
+ \fi}
+
+\def\font_helpers_set_math_family_bold#mbfam#familytag#mrfam%
+ {\ifconditional\optimizemathfontdefinitions
+ %\ifcsname\??fontinstanceclass\fontclass-\textface-\s!mm-#familytag-\fontsize-1\endcsname
+ \ifcsname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
+ \font_helpers_preset_math_family_indeed#mbfam#familytag%
+ \else
+ \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam%
+ \fi
+ \else
+ \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam%
+ \fi}
+
+%D It can happen that we use a bodyfont with no math in which case we have a problem
+%D with setting the global bodyfont size in the page builder. For instance in:
+%D
+%D \starttext
+%D \definetypeface[test][rm][serif][pagella][default]
+%D \setupbodyfont[test]
+%D test
+%D \stoptext
+%D
+%D This is why we need the check. At the cost of some extra checking we gain a
+%D little in restoring global states and, what's more important, we get rid of large
+%D math parameter push/pop in tracingall when not needed.
+
+\def\font_helpers_preset_math_family_indeed#fam#familytag%
+ {\expandafter\let\expandafter\v_font_math_one\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
+ \ifx\v_font_math_one\relax
+ \font_helpers_preset_math_family_warning
+ \orelse\ifnum\fontid\textfont#fam=\fontid\v_font_math_one\else
+ \font_helpers_preset_math_family_indeed_changed#fam#familytag%
+ \fi}
+
+\def\font_helpers_preset_math_family_warning
+ {\writestatus{fonts}{math: unset for global bodyfont \fontclass\space at \fontbody}}
+
+\def\font_helpers_preset_math_family_indeed_changed#fam#familytag%
+ {\scriptscriptfont#fam\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-3\endcsname
+ \scriptfont #fam\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-2\endcsname
+ \textfont #fam\v_font_math_one}
+
+\let\font_helpers_reset_fontclass_math_families\gobbleoneargument
+
+%D It would be nice if characters could be defined in a neutral way (say fam 255)
+%D and be mapped to a real family during noad list construction. However, this
+%D changes tex in critical places so for the moment we simulate this using
+%D manipulation.
+%D
+%D For tracing purposes we use three families but in l2r mode 1 and 2 are copies of
+%D 0 while in rl mode 0 is a copy of 1. There is no real overhead involved in this.
+%D This also permits different font definitions for normal and mixed.
+
+\let\m_font_class_direction\empty
+\let\m_font_class_features \empty
+\let\m_font_class_fallbacks\empty
+\let\m_font_class_goodies \empty
+
+\let\m_font_direction\empty
+\let\m_font_features \empty
+\let\m_font_fallbacks\empty
+\let\m_font_goodies \empty
+
+\appendtoks % can be analyzed once
+ % why here ..
+ %\edef\m_font_class_direction{\ifcsname\??fontclass\fontclass\s!mm\s!direction\endcsname\csname\??fontclass\fontclass\s!mm\s!direction\endcsname\fi}%
+ \edef\m_font_class_direction{\begincsname\??fontclass\fontclass\s!mm\s!direction\endcsname}%
+ % ...
+ \ifx\m_font_class_direction\v!both
+ \settrue\c_font_bidirectional_mathstrategy
+ \else
+ \setfalse\c_font_bidirectional_mathstrategy
+ \fi
+\to \t_font_math_strategies
+
+\def\font_helpers_bidirectional_mathstrategy_yes
+ {\font_helpers_set_math_family\c_font_fam_mr_lr\s!mrlr
+ \font_helpers_set_math_family\c_font_fam_mr_rl\s!mrrl
+ \ifnum\fontid\textfont\c_font_fam_mr=\fontid\textfont\c_font_fam_mr_lr\else
+ \font_helpers_bidirectional_mathstrategy_yes_changed
+ \fi}
+
+\def\font_helpers_bidirectional_mathstrategy_yes_changed
+ {\textfont \c_font_fam_mr\textfont \c_font_fam_mr_lr
+ \scriptfont \c_font_fam_mr\scriptfont \c_font_fam_mr_lr
+ \scriptscriptfont\c_font_fam_mr\scriptscriptfont\c_font_fam_mr_lr}
+
+\def\font_helpers_bidirectional_mathstrategy_nop
+ {\font_helpers_set_math_family\c_font_fam_mr\s!mr
+ \ifnum\fontid\textfont\c_font_fam_mr_rl=\fontid\textfont\c_font_fam_mr\else
+ \font_helpers_bidirectional_mathstrategy_nop_changed
+ \fi}
+
+\def\font_helpers_bidirectional_mathstrategy_nop_changed
+ {\textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mr_lr\scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr
+ \textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr}
+
+\appendtoks
+ \ifconditional\c_font_bidirectional_mathstrategy
+ \font_helpers_bidirectional_mathstrategy_yes
+ \else
+ \font_helpers_bidirectional_mathstrategy_nop
+ \fi
+\to \t_font_math_strategies
+
+\def\font_helpers_complete_bold_mathstrategy_yes_bidi
+ {\font_helpers_set_math_family_bold\c_font_fam_mb_lr\s!mblr\c_font_fam_mr_lr
+ \font_helpers_set_math_family_bold\c_font_fam_mb_rl\s!mbrl\c_font_fam_mr_rl
+ \ifnum\fontid\textfont\c_font_fam_mb=\fontid\textfont\c_font_fam_mb_lr\else
+ \font_helpers_complete_bold_mathstrategy_yes_bidi_changed
+ \fi}
+
+\def\font_helpers_complete_bold_mathstrategy_yes_bidi_changed
+ {\textfont \c_font_fam_mb\textfont \c_font_fam_mb_lr
+ \scriptfont \c_font_fam_mb\scriptfont \c_font_fam_mb_lr
+ \scriptscriptfont\c_font_fam_mb\scriptscriptfont\c_font_fam_mb_lr}
+
+\def\font_helpers_complete_bold_mathstrategy_yes
+ {\font_helpers_set_math_family_bold\c_font_fam_mb\s!mb\c_font_fam_mr\relax
+ \ifnum\fontid\textfont\c_font_fam_mb_rl=\fontid\textfont\c_font_fam_mb\else
+ \font_helpers_complete_bold_mathstrategy_yes_changed
+ \fi}
+
+\def\font_helpers_complete_bold_mathstrategy_yes_changed
+ {\textfont \c_font_fam_mb_rl\textfont \c_font_fam_mb
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mb
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mb
+ \textfont \c_font_fam_mb_lr\textfont \c_font_fam_mb
+ \scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mb
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mb}
+
+\def\font_helpers_complete_bold_mathstrategy_nop
+ {\ifnum\fontid\textfont\c_font_fam_mb=\fontid\textfont\c_font_fam_mr\else
+ \font_helpers_complete_bold_mathstrategy_nop_changed
+ \fi}
+
+\def\font_helpers_complete_bold_mathstrategy_nop_changed
+ {\textfont \c_font_fam_mb \textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mb \scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mb \scriptscriptfont\c_font_fam_mr
+ \textfont \c_font_fam_mb_lr\textfont \c_font_fam_mr_lr
+ \scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mr_lr
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr
+ \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl}
+
+\def\font_helpers_apply_complete_bold_mathstrategy
+ {\ifconditional\c_font_complete_bold_mathstrategy
+ \ifconditional\c_font_bidirectional_mathstrategy
+ \font_helpers_complete_bold_mathstrategy_yes_bidi
+ \else
+ \font_helpers_complete_bold_mathstrategy_yes
+ \fi
+ \else
+ \font_helpers_complete_bold_mathstrategy_nop
+ \fi}
+
+\appendtoks
+ \font_helpers_apply_complete_bold_mathstrategy
+\to \t_font_math_strategies
+
+\ifdefined\defaultmathfamily \else
+ \setnewconstant\defaultmathfamily\zerocount
+\fi
+
+\appendtoks
+ \fam\defaultmathfamily % all characters and symbols are in this family
+\to \everymathematics
+
+\unexpanded\def\font_helpers_synchronize_math_family_mr
+ {\attribute\mathfamilyattribute\ifconditional\c_font_bidirectional_mathstrategy
+ \ifconditional\c_math_right_to_left
+ \plustwo
+ \else
+ \plusone
+ \fi
+ \else
+ \zerocount
+ \fi}
+
+\unexpanded\def\font_helpers_synchronize_math_family_mb
+ {\attribute\mathfamilyattribute\ifconditional\c_font_bidirectional_mathstrategy
+ \ifconditional\c_math_right_to_left
+ \ifconditional\c_font_pseudo_bold_math_state\pluseight\else\plusfive\fi
+ \else
+ \ifconditional\c_font_pseudo_bold_math_state\plusseven\else\plusfour\fi
+ \fi
+ \else
+ \ifconditional\c_font_pseudo_bold_math_state\plussix\else\plusthree\fi
+ \fi}
+
+\installcorenamespace{fontmathsynchronizer}
+\installcorenamespace{fontmathstoredstrategy}
+
+\letvalue{\??fontmathsynchronizer\s!tf }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!sl }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!it }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!bf }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\s!bs }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\s!bi }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\empty}\font_helpers_synchronize_math_family_mr
+
+% \def\font_helpers_synchronize_math_family
+% {\csname\??fontmathsynchronizer\ifcsname\??fontmathsynchronizer\fontalternative\endcsname\fontalternative\fi\endcsname}
+
+\def\font_helpers_synchronize_math_family
+ {\ifcsname\??fontmathsynchronizer\fontalternative\endcsname
+ \lastnamedcs
+ \else
+ \font_helpers_synchronize_math_family_mr
+ \fi}
+
+\ifdefined \fontid % we need to keep this test for a while
+ \appendtoks
+ \ifnum\fontid\textfont\zerocount=\fontid\textfont\plusthree
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_partial_bold_strategy
+ \else
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_full_bold_strategy
+ \fi
+ \to \t_font_math_strategies
+\else
+ \appendtoks
+ \edef\currentmathfontmr{\fontname\textfont\zerocount}%
+ \edef\currentmathfontmb{\fontname\textfont\plusthree}%
+ \ifx\currentmathfontmr\currentmathfontmb
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_partial_bold_strategy
+ \else
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_full_bold_strategy
+ \fi
+ \to \t_font_math_strategies
+\fi
+
+%def\font_helpers_synchronize_math_bold_strategy{\csname\??fontmathstoredstrategy\fontclass\endcsname}
+\def\font_helpers_synchronize_math_bold_strategy{\begincsname\??fontmathstoredstrategy\fontclass\endcsname}
+
+\newconditional\c_font_pseudo_bold_math_state
+
+\def\font_helpers_set_math_partial_bold_strategy{\settrue \c_font_pseudo_bold_math_state}
+\def\font_helpers_set_math_full_bold_strategy {\setfalse\c_font_pseudo_bold_math_state}
+
+\appendtoks
+ \font_helpers_synchronize_math_bold_strategy
+\to \everymathematics
+
+%D Bold is somewhat special as we might want both full-bold-math mixed regular-math,
+%D as well as automatic adaption to outer bold (in titles and inline text bold) so
+%D we will need explicit switches as well as an automatic one. (We will use lucida
+%D as an example.)
+
+\ifdefined\mathdefault \else \let\mathdefault\relax \fi
+
+\newconditional\c_math_bold
+
+\unexpanded\def\mr % math regular
+ {\ifmmode
+ \font_helpers_synchronize_math_family_mr
+ \else
+ \font_helpers_set_current_font_alternative\s!mr
+ \fi
+ \mathdefault
+ \setfalse\c_math_bold}
+
+\unexpanded\def\mb % math bold
+ {\ifmmode
+ \font_helpers_synchronize_math_family_mb
+ \else
+ \font_helpers_set_current_font_alternative\s!mb
+ \fi
+ \mathdefault
+ \settrue\c_math_bold}
+
+\appendtoks
+ \font_helpers_synchronize_math_family % auto bold
+\to \everymathematics
+
+\appendtoks
+ \ifconditional\c_math_bold\mb\fi
+\to \everymathematics
+
+%D \macros
+%D {bigmath,nobigmath}
+%D
+%D We can inhibit this slow||downer with:
+
+% these can best be combined
+
+% 0=never 1=everymath 2=always
+
+\setnewconstant\synchronizebigmathflag\plusone
+
+\appendtoks
+ \ifcase\synchronizebigmathflag
+ % never
+ \or
+ \synchronizebigmath
+ \or
+ % always
+ \fi
+\to \everymathematics
+
+\unexpanded\def\nobigmath {\synchronizebigmathflag\zerocount}
+\unexpanded\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
+\unexpanded\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
+
+\let\bigmathfontsize\empty
+
+\unexpanded\def\synchronizebigmath
+ {\ifx\bigmathfontsize\fontsize
+ % already in sync
+ \else
+ \let\bigmathfontsize\fontsize
+ \font_helpers_synchronize_math
+ \fi}
+
+\unexpanded\def\font_helpers_check_big_math_synchronization
+ {\ifcase\synchronizebigmathflag
+ % never
+ \or
+ \ifmmode \synchronizebigmath \fi
+ \or
+ \synchronizebigmath
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua
index 76d7390b6..4fe0a6a97 100644
--- a/tex/context/base/mkiv/font-otr.lua
+++ b/tex/context/base/mkiv/font-otr.lua
@@ -1215,7 +1215,7 @@ readers.vmtx = function(f,fontdata,specification)
local topsidebearing = 0
for i=0,nofmetrics-1 do
local glyph = glyphs[i]
- vheight = readshort(f)
+ vheight = readushort(f)
topsidebearing = readshort(f)
if vheight ~= 0 and vheight ~= vdefault then
glyph.vheight = vheight
@@ -1315,14 +1315,16 @@ local formatreaders = { }
local duplicatestoo = true
local sequence = {
+ -- these is some provision against redundant loading
{ 3, 1, 4 },
{ 3, 10, 12 },
{ 0, 3, 4 },
+ { 0, 3, 12 },
{ 0, 1, 4 },
- -- { 0, 1, 12 }, -- maybe for some old mac fonts
- -- { 0, 4, 12 },
+ { 0, 1, 12 }, -- for some old mac fonts
{ 0, 0, 6 },
{ 3, 0, 6 },
+ { 3, 0, 4 }, -- for (likely) old crap
-- variants
{ 0, 5, 14 },
-- last resort ranges
@@ -1633,24 +1635,33 @@ formatreaders[14] = function(f,fontdata,offset)
end
local function checkcmap(f,fontdata,records,platform,encoding,format)
- local data = records[platform]
- if not data then
+ local pdata = records[platform]
+ if not pdata then
if trace_cmap_details then
report_cmap("skipped, %s, p=%i e=%i f=%i","no platform",platform,encoding,format)
end
return 0
end
- data = data[encoding]
- if not data then
+ local edata = pdata[encoding]
+ if not edata then
if trace_cmap_details then
report_cmap("skipped, %s, p=%i e=%i f=%i","no encoding",platform,encoding,format)
end
return 0
end
- data = data[format]
- if not data then
+ local fdata = edata[format]
+ if not fdata then
+ if trace_cmap_details then
+ report_cmap("skipped, %s, p=%i e=%i f=%i","no format",platform,encoding,format)
+ end
+ return 0
+ elseif type(fdata) ~= "number" then
+ if trace_cmap_details then
+ report_cmap("skipped, %s, p=%i e=%i f=%i","already done",platform,encoding,format)
+ end
return 0
end
+ edata[format] = true -- done
local reader = formatreaders[format]
if not reader then
if trace_cmap_details then
@@ -1658,8 +1669,8 @@ local function checkcmap(f,fontdata,records,platform,encoding,format)
end
return 0
end
- local n = reader(f,fontdata,data) or 0
- if trace_cmap then
+ local n = reader(f,fontdata,fdata) or 0
+ if trace_cmap_details or trace_cmap then
local p = platforms[platform]
local e = encodings[p]
report_cmap("checked, platform %i (%s), encoding %i (%s), format %i, new unicodes %i",
diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv
index c1c24b854..d17f57167 100644
--- a/tex/context/base/mkiv/font-pre.mkiv
+++ b/tex/context/base/mkiv/font-pre.mkiv
@@ -755,6 +755,8 @@
\definealternativestyle [italicface] [\italicface] []
\definealternativestyle [swapface] [\swapface] []
+\definealternativestyle [emphasize] [\em] [\em] % new
+
% For Alan:
\definealternativestyle
diff --git a/tex/context/base/mkiv/font-shp.lua b/tex/context/base/mkiv/font-shp.lua
index 631f3086e..ba4853ec3 100644
--- a/tex/context/base/mkiv/font-shp.lua
+++ b/tex/context/base/mkiv/font-shp.lua
@@ -23,6 +23,10 @@ local streamscache = containers.define("fonts", "streams", version, true)
-- shapes (can be come a separate file at some point)
+local compact_streams = false
+
+directives.register("fonts.streams.compact", function(v) compact_streams = v end)
+
local function packoutlines(data,makesequence)
local subfonts = data.subfonts
if subfonts then
@@ -209,6 +213,16 @@ local function loadoutlines(cache,filename,sub,instance)
return data
end
+local function cachethem(cache,hash,data)
+ local fast = caches.fast
+ if compact_streams then
+ caches.fast = true
+ end
+ containers.write(cache,hash,data)
+ caches.fast = fast
+ return containers.read(cache,hash) -- frees old mem
+end
+
local function loadstreams(cache,filename,sub,instance)
local base = file.basename(filename)
local name = file.removesuffix(base)
@@ -240,8 +254,7 @@ local function loadstreams(cache,filename,sub,instance)
data.size = size
data.format = data.format or (kind == "otf" and "opentype") or "truetype"
data.time = time
- containers.write(cache,hash,data)
- data = containers.read(cache,hash) -- frees old mem
+ data = cachethem(cache,hash,data)
end
end
elseif size > 0 and (kind == "pfb") then
@@ -295,8 +308,7 @@ local function loadstreams(cache,filename,sub,instance)
weight = metadata.weight,
},
}
- containers.write(cache,hash,data)
- data = containers.read(cache,hash) -- frees old mem
+ data = cachethem(cache,hash,data)
end
end
else
diff --git a/tex/context/base/mkiv/font-sty.mklx b/tex/context/base/mkiv/font-sty.mklx
new file mode 100644
index 000000000..385a9cdbe
--- /dev/null
+++ b/tex/context/base/mkiv/font-sty.mklx
@@ -0,0 +1,449 @@
+%D \module
+%D [ file=font-sty,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Styles,
+%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.
+
+\writestatus{loading}{ConTeXt Font Macros / Styles}
+
+\unprotect
+
+%D \macros
+%D {definealternativestyle}
+%D
+%D In the main modules we are going to implement lots of parameterized commands and
+%D one of these parameters will concern the font to use. To suit consistent use of
+%D fonts we here implement a mechanism for defining the keywords that present a
+%D particular style or alternative.
+%D
+%D \starttyping
+%D \definealternativestyle [keywords] [\style] [\nostyle]
+%D \stoptyping
+%D
+%D The first command is used in the normal textflow, while the second command takes
+%D care of headings and alike. Consider the next two definitions:
+%D
+%D \starttyping
+%D \definealternativestyle [bold] [\bf] []
+%D \definealternativestyle [cap] [\cap] [\cap]
+%D \stoptyping
+%D
+%D A change \type {\bf} in a heading which is to be set in \type {\tfd} does not look
+%D that well, so therefore we leave the second argument of \type
+%D {\definealternativestyle} empty. When we capatalize characters using the pseudo
+%D small cap command \type {\cap}, we want this to take effect in both text and
+%D headings, which is accomplished by assigning both arguments.
+
+\installcorenamespace{alternativestyles} % settings
+\installcorenamespace{alternativestyle} % instances
+
+\installsetuponlycommandhandler \??alternativestyles {alternativestyles}
+
+\setnewconstant \c_font_current_alternative_style_index \plusone
+
+\unexpanded\def\definealternativestyle
+ {\dotripleempty\font_basics_define_alternative_style}
+
+\def\font_basics_define_alternative_style[#commands][#variantone][#varianttwo]%
+ {\processcommalist[#commands]{\font_basics_define_alternative_style_indeed{#variantone}{#varianttwo}}}
+
+\let\definestyle\definealternativestyle % later redefined
+
+\newconstant\c_fonts_basics_alternative_style_method
+
+\def\font_basics_define_alternative_style_indeed#variantone#varianttwo#command%
+ {\setuvalue{\??alternativestyle#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}%
+ \ifcsname#command\endcsname
+ % no redefinition
+ \orelse\ifnum\c_fonts_basics_alternative_style_method=\plusone
+ \ifthirdargument
+ \setuevalue{#command}{\triggergroupedcommandcs\begincsname\??alternativestyle#command\endcsname}%
+ \else
+ \setuvalue{#command}{\triggergroupedcommand{#variantone}}%
+ \fi
+ \else
+ \setuvalue{#command}{\triggergroupedcommand{#variantone}}%
+ \fi}
+
+\def\font_helpers_apply_alternative_style
+ {\ifcase\c_font_current_alternative_style_index
+ \expandafter\gobbletwoarguments
+ \or
+ \expandafter\firstoftwoarguments
+ \or
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\applyalternativestyle#name% public
+ {\begincsname\??alternativestyle#name\endcsname}
+
+\appendtoks
+ \doifelse{\alternativestylesparameter\c!method}\v!auto
+ {\c_fonts_basics_alternative_style_method\plusone}%
+ {\c_fonts_basics_alternative_style_method\zerocount}%
+\to \everysetupalternativestyles
+
+%D Maybe too generic, but probably ok is the following. (Maybe one day we will use a
+%D dedicated grouped command for styles.)
+
+% \appendtoks
+% \let\groupedcommand\thirdofthreearguments
+% \to \everysimplifycommands
+
+%D This command also defines the keyword as command. This means that the example
+%D definition of \type {bold} we gave before, results in a command \type {\bold}
+%D which can be used as:
+%D
+%D \startbuffer
+%D He's a \bold{bold} man with a {\bold head}.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startexample
+%D \definealternativestyle[bold][\bf][]\getbuffer
+%D \stopexample
+%D
+%D Such definitions are of course unwanted for \type {\cap} because this would
+%D result in an endless recursive call. Therefore we check on the existance of both
+%D the command and the substitution. The latter is needed because for instance \type
+%D {\type} is an entirely diferent command. That command handles verbatim, while the
+%D style command would just switch to teletype font. This is just an example of a
+%D tricky naming coincidence.
+%D
+%D \macros
+%D {doconvertfont,noconvertfont,
+%D dontconvertfont,redoconvertfont}
+%D
+%D After having defined such keywords, we can call for them by using
+%D
+%D \starttyping
+%D \doconvertfont{keyword}{text}
+%D \stoptyping
+%D
+%D We deliberately pass an argument. This enables us to assign converters that
+%D handle one argument, like \type {\cap}.
+%D
+%D By default the first specification is used to set the style, exept when we say
+%D \type {\dontconvertfont}, after which the second specification is used. We can
+%D also directly call for \type {\noconvertfont}. In nested calls, we can restore
+%D the conversion by saying \type {\redoconvertfont}.
+%D
+%D These commands are not grouped! Grouping is most probably done by the calling
+%D macro's and would lead to unnecessary overhead.
+
+\let\m_current_convert_font \empty
+\let\m_current_convert_font_dt\empty
+
+\unexpanded\def\doconvertfont#specification% takes second argument / this command is obsolete
+ {\edef\m_current_convert_font{#specification}%
+ \ifx\m_current_convert_font\empty
+ %\expandafter\firstofoneargument
+ \else
+ \expandafter\font_helpers_do_convert_font
+ \fi}
+
+\def\font_helpers_do_convert_font
+ {\edef\m_current_convert_font_dt{\detokenize\expandafter{\m_current_convert_font}}%
+ \ifcsname\??alternativestyle\m_current_convert_font_dt\endcsname
+ \expandafter\lastnamedcs
+ \orelse\ifcsname\m_current_convert_font_dt\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\m_current_convert_font
+ \fi}
+
+%D Low level switches (downward compatible, but we keep them as one can use them in
+%D styles):
+%D
+%D \starttyping
+%D \usemodule[abr-02]
+%D \setuphead[chapter][style=\bfb]
+%D \setupfooter[style=\dontconvertfont\bf]
+%D \chapter{This is \TEX}
+%D \stoptyping
+
+\unexpanded\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage
+\unexpanded\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage
+
+%D The new one:
+
+\setfalse\fontattributeisset
+
+\unexpanded\def\dousestyleparameter#value%
+ {\edef\currentstyleparameter{#value}%
+ \ifx\currentstyleparameter\empty\else
+ \expandafter\dousecurrentstyleparameter
+ \fi}
+
+\unexpanded\def\dousestylehashparameter#hash#parameter%
+ {\ifcsname#hash#parameter\endcsname
+ \expandafter\dousestyleparameter\lastnamedcs
+ \fi}
+
+\unexpanded\def\dousecurrentstyleparameter % empty check outside here
+ {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
+ \settrue\fontattributeisset % reset is done elsewhere
+ \ifcsname\??alternativestyle\detokenizedstyleparameter\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\detokenizedstyleparameter\endcsname
+ \lastnamedcs
+ \else
+ \currentstyleparameter
+ \fi}
+
+\let\dosetfontattribute\dousestylehashparameter % for a while
+
+%D New commands (not yet interfaced):
+%D
+%D \startbuffer
+%D \definestyle[one][style=bold,color=darkblue]
+%D
+%D test \one{test} test
+%D test \style[one]{test} test
+%D test \style[color=red]{test} test
+%D test \style[Serif at 20pt]{test} test
+%D \stopbuffer
+%D
+%D \typebuffer \startlines \getbuffer \stoplines
+
+% definitions .. no tagging here
+
+\installcorenamespace{style}
+\installcorenamespace{stylecheck}
+
+\installcommandhandler \??style {style} \??style
+
+\setupstyle
+ [%\c!style=,
+ %\c!color=,
+ \c!method=\v!command]
+
+\appendtoks
+ \letvalue{\??stylecheck\currentstyle}\relax
+ \edef\p_method{\styleparameter\c!method}%
+ \ifx\p_method\v!command
+ \setuevalue{\e!start\currentstyle}{\font_styles_apply_start{\currentstyle}}%
+ \setuevalue{\e!stop \currentstyle}{\font_styles_apply_stop}%
+ \setuevalue {\currentstyle}{\font_styles_apply_grouped{\currentstyle}}% no longer groupedcommand here
+ \fi
+\to \everydefinestyle
+
+\unexpanded\def\font_styles_apply_start#name%
+ {\begingroup
+ \font_styles_use_defined{#name}}
+
+\unexpanded\def\font_styles_apply_stop
+ {\endgroup}
+
+\unexpanded\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup
+ {\bgroup
+ \def\g_style{\font_styles_use_defined{#name}}%
+ \afterassignment\g_style
+ \let\nexttoken}
+
+\unexpanded\def\font_styles_use_defined#name%
+ {\edef\currentstyle{#name}%
+ \usestylestyleandcolor\c!style\c!color}
+
+\unexpanded\def\font_styles_use_generic#specification%
+ {\let\currentstyle\s!unknown % reasonable generic tag
+ \letstyleparameter\c!style\empty
+ \letstyleparameter\c!color\empty
+ \setupcurrentstyle[#specification]%
+ \usestylestyleandcolor\c!style\c!color}
+
+% commands
+
+\installcorenamespace{styleargument}
+
+\unexpanded\def\style[#name]% as this is can be a switch we use groupedcommand
+ {\csname\??styleargument
+ \ifcsname\??stylecheck#name\endcsname
+ 2% defined as style
+ \orelse\ifcsname#name\endcsname
+ 1% defined as command
+ \else
+ 3% specification
+ \fi
+ \endcsname{#name}}
+
+% \setvalue{\??styleargument1}#name%
+% {\groupedcommand{\begincsname#name\endcsname}{}}
+
+\setvalue{\??styleargument1}#name%
+ {\expandafter\triggergroupedcommandcs\begincsname#name\endcsname}
+
+% \setvalue{\??styleargument2}#name%
+% {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}}
+
+\setvalue{\??styleargument2}#name%
+ {\triggergroupedcommand{\font_styles_use_defined{#name}}} % or {\font_styles_apply_grouped{#name}}
+
+\setvalue{\??styleargument3}#specification%
+ {\doifelseassignment{#specification}\font_styles_assignment\font_styles_direct{#specification}}
+
+% \def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}}
+% \def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}}
+
+\def\font_styles_assignment#specification{\triggergroupedcommand{\font_styles_use_generic{#specification}}}
+\def\font_styles_direct #specification{\triggergroupedcommand{\definedfont[#specification]}}
+
+% environments
+
+\installcorenamespace{styleenvironment}
+
+\unexpanded\def\startstyle[#name]%
+ {\begingroup
+ \csname\??styleenvironment
+ \ifcsname\??stylecheck#name\endcsname
+ 2% defined as style
+ \orelse\ifcsname#name\endcsname
+ 1% defined as command
+ \else
+ 3% specification
+ \fi
+ \endcsname{#name}}
+
+\unexpanded\def\stopstyle
+ {\endgroup
+ \autoinsertnextspace} % will be configurable, maybe also in \definestartstop
+
+\setvalue{\??styleenvironment1}#name%
+ {\csname#name\endcsname}
+
+\setvalue{\??styleenvironment2}#name%
+ {\font_styles_use_defined{#name}}
+
+\setvalue{\??styleenvironment3}#specification%
+ {\doifelseassignment{#specification}\font_styles_start_assignment\font_styles_start_direct{#specification}}
+
+\def\font_styles_start_assignment#specification{\font_styles_use_generic{#specification}}
+\def\font_styles_start_direct #specification{\definedfont[#specification]\relax}
+
+%D Still experimental (might even go away).
+
+% \definestylecollection[mine]
+
+% \definestyleinstance[mine][default][sorry]
+% \definestyleinstance[mine][tt][bs][ttbs:\rm\sl]
+% \definestyleinstance[mine][tt][bf][ttbf:\rm\sl]
+% \definestyleinstance[mine][bf][\sl]
+% \definestyleinstance[mine][sl][\tt]
+
+% {\bf test \mine test \sl test \mine test \bs oeps \mine oeps {\tt test \mine \bf test}}
+
+\installcorenamespace{stylecollection}
+
+\unexpanded\def\definestylecollection
+ {\dosingleargument\font_styles_define_style_collection}
+
+\def\font_styles_define_style_collection[#name]%
+ {\iffirstargument
+ \setuvalue{#name}{\styleinstance[#name]}%
+ \def\font_styles_define_style_collection_a#style%
+ {\def\font_styles_define_style_collection_b#alternative{\undefinevalue{\??stylecollection#name:#style:#alternative}}%
+ \font_helpers_process_alternative_list\font_styles_define_style_collection_b
+ \font_styles_define_style_collection_b\s!default}%
+ \font_helpers_process_style_list\font_styles_define_style_collection_a
+ \font_styles_define_style_collection_a\s!default
+ \fi}
+
+\let\font_styles_define_style_collection_a\relax
+\let\font_styles_define_style_collection_b\relax
+
+\unexpanded\def\definestyleinstance
+ {\doquadrupleargument\font_styles_define_style_instance}
+
+\def\font_styles_define_style_instance[#instance][#2][#3][#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever]
+ {\iffirstargument
+ \ifcsname#instance\endcsname\else\font_styles_define_style_collection[#instance]\fi
+ \fi
+ \iffourthargument
+ \setvalue{\??stylecollection#instance:#2:#3}{#4}%
+ \orelse\ifthirdargument
+ \setvalue{\??stylecollection#instance::#2}{#3}%
+ \orelse\ifsecondargument
+ \letvalueempty{\??stylecollection#instance::#2}%
+ \fi}
+
+% \unexpanded\def\styleinstance[#instance]% will be made faster
+% {%\begingroup\normalexpanded{\noexpand\infofont[#1:\fontstyle:\fontalternative]}\endgroup
+% \executeifdefined{\??stylecollection#instance:\fontstyle:\fontalternative}%
+% {\executeifdefined{\??stylecollection#instance:\fontstyle:\s!default}%
+% {\executeifdefined{\??stylecollection#instance::\fontalternative}
+% {\getvalue {\??stylecollection#instance::\s!default}}}}}
+
+\unexpanded\def\styleinstance[#instance]% maybe \lastnamedcs here too
+ {\csname\??stylecollection#instance:%
+ \ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname
+ \fontstyle:\fontalternative
+ \orelse\ifcsname\??stylecollection#instance:\fontstyle:\s!default\endcsname
+ \fontstyle:\s!default
+ \orelse\ifcsname\??stylecollection#instance::\fontalternative\endcsname
+ :\fontalternative
+ \else
+ :\s!default
+ \fi
+ \endcsname}
+
+%D Variant selectors
+%D
+%D \starttyping
+%D \mathematics {\vsone{\utfchar{0x2229}}}
+%D \mathematics {\utfchar{0x2229}\vsone{}}
+%D \stoptyping
+
+\unexpanded\edef\vsone#character{#character\normalUchar"FE00 } % used
+\unexpanded\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing
+
+%D For historic reasons we keep the following around but they are no longer that
+%D relevant for \MKIV.
+
+\unexpanded\def\doattributes#1#2#3#4%
+ {\begingroup % geen \bgroup, anders in mathmode lege \hbox
+ \dousestylehashparameter{#1}{#2}%
+ \dousecolorhashparameter{#1}{#3}%
+ #4%
+ \endgroup}
+
+\unexpanded\def\dostartattributes#1#2#3%
+ {\begingroup % geen \bgroup, anders in mathmode lege \hbox
+ \dousestylehashparameter{#1}{#2}%
+ \dousecolorhashparameter{#1}{#3}}
+
+\let\dostopattributes\endgroup
+
+%D New but it needs to be supported explicitly (as in natural tables).
+
+\newconditional\c_font_styles_math
+
+\unexpanded\def\font_styles_math_reset
+ {\setfalse\c_font_styles_math}
+
+\unexpanded\def\font_styles_math_start
+ {\ifconditional\c_font_styles_math
+ \startimath
+ \fi
+ \relax}
+
+\unexpanded\def\font_styles_math_stop
+ {\relax
+ \ifconditional\c_font_styles_math
+ \stopimath
+ \fi}
+
+\definealternativestyle[\v!math][\settrue\c_font_styles_math]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-sym.mklx b/tex/context/base/mkiv/font-sym.mklx
new file mode 100644
index 000000000..33f8a62da
--- /dev/null
+++ b/tex/context/base/mkiv/font-sym.mklx
@@ -0,0 +1,245 @@
+%D \module
+%D [ file=font-mat,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Symbolic Access,
+%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.
+
+\writestatus{loading}{ConTeXt Font Macros / Symbolic Access}
+
+\unprotect
+
+%D \macros
+%D {getglyph, symbolicfont}
+%D
+%D Individual glyphs can be accessed by using
+%D
+%D \starttyping
+%D \getglyph{fontname}{character}
+%D \stoptyping
+%D
+%D This macro is used in for instance the symbol modules and as one can see, it does
+%D obey the small and even smaller sizes. The \type {\symbolicfont} macro can be
+%D used to switch to a font named \type {fontname} (see \type {cont-log} and \type
+%D {symb-eur} for examples of symbolic definitions.
+
+\def\v_font_string_a
+ {\ifx\fontstyle\s!rm \s!Serif \orelse
+ \ifx\fontstyle\s!ss \s!Sans \orelse
+ \ifx\fontstyle\s!tt \s!Mono \else
+ \s!Serif \fi}
+
+\def\v_font_string_b
+ {\ifx\fontstyle\s!rm \s!Regular \orelse
+ \ifx\fontstyle\s!ss \s!Support \orelse
+ \ifx\fontstyle\s!tt \s!Type \else
+ \s!Serif \fi}
+
+\def\v_font_string_c
+ {\ifx\fontalternative\s!bf \s!Bold \orelse
+ \ifx\fontalternative\s!sl \s!Slanted \orelse
+ \ifx\fontalternative\s!it \s!Italic \orelse
+ \ifx\fontalternative\s!bs \s!BoldSlanted \orelse
+ \ifx\fontalternative\s!bi \s!BoldItalic \fi}
+
+\let\v_font_string_d\s!Serif % default fontstyle (will be redefined in type-ini)
+
+\definefontsynonym
+ [CurrentFont]
+ [\noexpand\v_font_string_a\noexpand\v_font_string_c]
+
+% potential generalization:
+%
+% \letvalue{\??fontfile:t:\s!rm}\s!Serif
+% \letvalue{\??fontfile:t:\s!ss}\s!Sans
+% \letvalue{\??fontfile:t:\s!tt}\s!Mono
+%
+% \letvalue{\??fontfile:a:\s!rm}\s!Regular
+% \letvalue{\??fontfile:a:\s!ss}\s!Support
+% \letvalue{\??fontfile:a:\s!tt}\s!Type
+%
+% \letvalue{\??fontfile:s:\s!bf}\s!Bold
+% \letvalue{\??fontfile:s:\s!sl}\s!Slanted
+% \letvalue{\??fontfile:s:\s!it}\s!Italic
+% \letvalue{\??fontfile:s:\s!bs}\s!BoldSlanted
+% \letvalue{\??fontfile:s:\s!bi}\s!BoldItalic
+%
+% \def\v_font_string_a{\executeifdefined{\??fontfile:t:\fontstyle}\s!Serif}
+% \def\v_font_string_a{\executeifdefined{\??fontfile:t:\fontstyle}\s!Serif}
+% \def\v_font_string_b{\executeifdefined{\??fontfile:a:\fontstyle}\s!Serif}
+% \def\v_font_string_c{\executeifdefined{\??fontfile:s:\fontstyle}\empty}
+% \def\v_font_string_d{\executeifdefined{\??fontfile:t:\csname\??typescriptdefaultstyles\fontclass\endcsname}\s!Serif}
+
+%D \macros
+%D {fontstylesuffix}
+%D
+%D The next macro is used to map non latin fontnames on fonts. See \type
+%D {font-uni} for an example of its use.
+
+\def\fontstylesuffix% why the \s!Regular ? see \getglyph
+ {\ifx\fontalternative\s!tf \s!Regular \orelse
+ \ifx\fontalternative\s!bf \s!Bold \orelse
+ \ifx\fontalternative\s!sl \s!Slanted \orelse
+ \ifx\fontalternative\s!it \s!Italic \orelse
+ \ifx\fontalternative\s!bs \s!BoldSlanted \orelse
+ \ifx\fontalternative\s!bi \s!BoldItalic \orelse
+ \ifx\fontalternative\s!sc \s!Caps \else
+ \s!Regular \fi}
+
+\def\glyphfontfile#base% appends
+ {#base%
+ \ifcsname\??fontfile#base\v_font_string_a\v_font_string_c\endcsname
+ \v_font_string_a\v_font_string_c
+ \orelse\ifcsname\??fontfile#base\v_font_string_b\v_font_string_c\endcsname
+ \v_font_string_b\v_font_string_c
+ \orelse\ifcsname\??fontfile#base\v_font_string_a\endcsname
+ \v_font_string_a
+ \orelse\ifcsname\??fontfile#base\v_font_string_b\endcsname
+ \v_font_string_b
+ \orelse\ifcsname\??fontfile#base\v_font_string_c\endcsname
+ \v_font_string_c
+ \fi}
+
+%D The next macro can be used to make decisions based on the shape:
+
+\def\doifelseitalic#yes#nop%
+ {\ifx\fontalternative\s!sl#yes\orelse
+ \ifx\fontalternative\s!it#yes\orelse
+ \ifx\fontalternative\s!bs#yes\orelse
+ \ifx\fontalternative\s!bi#yes\else#nop\fi}
+
+\let\doifitalicelse\doifelseitalic
+
+%D For an example of usage of the following command, see \type {cont-log.tex}.
+%D
+%D \starttyping
+%D \def\symbolicfont#specification{\definedfont[\glyphfontfile{#specification} sa *]}
+%D \stoptyping
+%D
+%D Since we know what scaling it to be applied, we can implement a much faster
+%D alternative:
+
+\installcorenamespace{symbolfont}
+
+\let\thedefinedfont\relax
+
+\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
+ {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
+ {\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile
+ {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setdirectsymbolicfont#fontname%
+ {\edef\askedsymbolfont{\truefontname{#fontname} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\font_basics_define_symbolic_font
+ {\definefont[currentsymbolfont][\askedsymbolfont]%
+ \currentsymbolfont
+ \expandafter\glet\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall}
+
+\unexpanded\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}}
+\unexpanded\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}}
+\unexpanded\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
+\unexpanded\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
+\unexpanded\def\resolvedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_tochar{#character}}}
+\unexpanded\def\resolvedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_tochar{#character}}}
+
+% this one is wrong:
+
+\unexpanded\def\getscaledglyph#scale#name#content%
+ {{\setscaledstyledsymbolicfont\fontbody{#scale}{#name}\doifelsenumber{#content}\char\donothing#content}}
+
+\let\getglyph \getglyphstyled % old
+\let\getrawglyph \getglyphdirect % old
+\let\symbolicsizedfont\setscaledstyledsymbolicfont % old
+\let\symbolicfont \setstyledsymbolicfont % old
+
+\unexpanded\def\symbolicscaledfont{\setsscaledstyledsymbolicfont\fontbody}
+\unexpanded\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody}
+
+%D The last implementation of \type {\getglyph} permits definitions like:
+%D
+%D \starttyping
+%D \definefontsynonym [EuroSans] [eurose]
+%D \definefontsynonym [EuroSansBold] [euroseb]
+%D \definefontsynonym [EuroSansItalic] [eurosei]
+%D \definefontsynonym [EuroSansSlanted] [eurosei]
+%D \definefontsynonym [EuroSansBoldItalic] [eurosebi]
+%D \definefontsynonym [EuroSansBoldSlanted] [eurosebi]
+%D
+%D \definesymbol [euro] [\getglyph{Euro}{\char160}]
+%D
+%D \def\euro{\symbol[euro]}
+%D \stoptyping
+%D
+%D These definitions guarantee that the next calls work okay:
+%D
+%D \starttyping
+%D \ss \tf\euro \bf\euro \sla\euro \itd\euro \bs\euro \bic\euro
+%D \stoptyping
+%D
+%D The shape as well as the size is adapted to the current environment.
+
+%D \macros
+%D {setfont}
+%D
+%D Every now and then we want to define a font directly, for instance when we
+%D typeset title pages. The next macro saves some typing:
+
+\unexpanded\def\setfont% geen \font_helpers_set_font mogelijk
+ {\afterassignment\font_basics_set_font\font\nextfont=}
+
+\def\font_basics_set_font
+ {\nextfont\setupinterlinespace}% hm, we need to use \setuplocalinterlinespace
+
+%D One can call this macro as:
+%D
+%D \starttyping
+%D \setfont cmr10 at 60pt
+%D \stoptyping
+%D
+%D After which the font is active and the baselines and struts are set.
+
+%D \macros{doiffontcharelse}
+
+\unexpanded\def\doifelsefontchar#specification#unicode% this could be a direct lua call
+ {\begingroup
+ \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
+ \iffontchar\font#unicode\relax
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiffontcharelse\doifelsefontchar
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-sym.mkvi b/tex/context/base/mkiv/font-sym.mkvi
index 3ff85fb4a..b6479535b 100644
--- a/tex/context/base/mkiv/font-sym.mkvi
+++ b/tex/context/base/mkiv/font-sym.mkvi
@@ -24,12 +24,10 @@
%D \getglyph{fontname}{character}
%D \stoptyping
%D
-%D This macro is used in for instance the symbol modules and
-%D as one can see, it does obey the small and even smaller
-%D sizes. The \type {\symbolicfont} macro can be used to
-%D switch to a font named \type {fontname} (see \type
-%D {cont-log} and \type {symb-eur} for examples of symbolic
-%D definitions.
+%D This macro is used in for instance the symbol modules and as one can see, it does
+%D obey the small and even smaller sizes. The \type {\symbolicfont} macro can be
+%D used to switch to a font named \type {fontname} (see \type {cont-log} and \type
+%D {symb-eur} for examples of symbolic definitions.
\def\v_font_string_a
{\ifx\fontstyle\s!rm \s!Serif \else
@@ -118,15 +116,14 @@
\let\doifitalicelse\doifelseitalic
-%D For an example of usage of the following command,
-%D see \type {cont-log.tex}.
+%D For an example of usage of the following command, see \type {cont-log.tex}.
%D
%D \starttyping
%D \def\symbolicfont#specification{\definedfont[\glyphfontfile{#specification} sa *]}
%D \stoptyping
%D
-%D Since we know what scaling it to be applied, we can
-%D implement a much faster alternative:
+%D Since we know what scaling it to be applied, we can implement a much faster
+%D alternative:
\installcorenamespace{symbolfont}
@@ -189,8 +186,7 @@
\unexpanded\def\symbolicscaledfont{\setsscaledstyledsymbolicfont\fontbody}
\unexpanded\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody}
-%D The last implementation of \type {\getglyph} permits
-%D definitions like:
+%D The last implementation of \type {\getglyph} permits definitions like:
%D
%D \starttyping
%D \definefontsynonym [EuroSans] [eurose]
@@ -211,15 +207,13 @@
%D \ss \tf\euro \bf\euro \sla\euro \itd\euro \bs\euro \bic\euro
%D \stoptyping
%D
-%D The shape as well as the size is adapted to the current
-%D environment.
+%D The shape as well as the size is adapted to the current environment.
%D \macros
%D {setfont}
%D
-%D Every now and then we want to define a font directly, for
-%D instance when we typeset title pages. The next macro saves
-%D some typing:
+%D Every now and then we want to define a font directly, for instance when we
+%D typeset title pages. The next macro saves some typing:
\unexpanded\def\setfont% geen \font_helpers_set_font mogelijk
{\afterassignment\font_basics_set_font\font\nextfont=}
@@ -233,8 +227,7 @@
%D \setfont cmr10 at 60pt
%D \stoptyping
%D
-%D After which the font is active and the baselines and
-%D struts are set.
+%D After which the font is active and the baselines and struts are set.
%D \macros{doiffontcharelse}
diff --git a/tex/context/base/mkiv/lang-ini.mkxl b/tex/context/base/mkiv/lang-ini.mkxl
new file mode 100644
index 000000000..8bcba01d8
--- /dev/null
+++ b/tex/context/base/mkiv/lang-ini.mkxl
@@ -0,0 +1,730 @@
+%D \module
+%D [ file=lang-ini,
+%D version=1996.01.25,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module needs a further cleanup (real split between ii/iv).
+
+% \cldcontext{languages.numbers[tex.count.mainlanguagenumber]}
+
+%D This module implements multi||language support of \CONTEXT, which should not be
+%D confused with the multi||lingual interface. This support will be extended when
+%D needed. Properties of languages are defined in \TEX\ files as well as \LUA\
+%D files.
+
+\writestatus{loading}{ConTeXt Language Macros / Initialization}
+
+\registerctxluafile{lang-ini}{}
+\registerctxluafile{lang-def}{}
+\registerctxluafile{lang-cnt}{}
+
+\unprotect
+
+\ifdefined\nonfrenchspacing\else \let\nonfrenchspacing\relax \fi
+\ifdefined\frenchspacing \else \let\frenchspacing \relax \fi
+
+%D When loading hyphenation patterns, \TEX\ assign a number to each loaded table,
+%D starting with~0. Switching to a specific table is done by assigning the relevant
+%D number to the predefined \COUNTER\ \type {\language}. However, in \MKIV\ a lot
+%D of management is delegated to \LUA.
+
+%D We keep track of the last loaded patterns by means of a pseudo \COUNTER. This
+%D just one of those situations in which we don't want to spent a real one. Language
+%D zero has no patterns, first of all because I like to start numbering at one. It
+%D may come in handy for special purposes as well.
+
+\normallanguage\zerocount \def\loadedlanguage{1}
+
+%D \macros
+%D {currentlanguage, setupcurrentlanguage}
+%D
+%D Instead of numbers,we are going to use symbolic names for the languages. The
+%D current langage is saved in the macro \type {\currentlanguage}. The setup macro
+%D is mainly used for cosmetic purposes.
+%D
+%D \starttyping
+%D \dorecurse{3}
+%D {\language[nl]
+%D \startmode[*en] english \stopmode
+%D \startmode[*nl] dutch \stopmode
+%D \language[en]
+%D \startmode[*en] english \stopmode
+%D \startmode[*nl] dutch \stopmode}
+%D \stoptyping
+
+\let\currentlanguage \empty
+\let\currentmainlanguage\empty
+
+%D \macros
+%D {defaultlanguage,languageparameter,specificlanguageparameter}
+%D
+%D We don't use the commandhandler here (yet) because we have a rather special
+%D fallback mechanism so quite some compatibility testing is needed.
+
+\installcorenamespace{language}
+\installcorenamespace{languagelinked}
+
+\def\currentusedlanguage{\currentlanguage}
+
+\def\defaultlanguage#1%
+ {\ifcsname\??language#1\s!default\endcsname
+ \expandafter\defaultlanguage\lastnamedcs
+ \else
+ #1%
+ \fi}
+
+\def\languageparameter#1%
+ {\ifcsname\??language\currentlanguage#1\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??language\currentlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#1}%
+ \orelse\ifcsname\??language\s!default#1\endcsname
+ \lastnamedcs
+ \fi}
+
+\def\specificlanguageparameter#1#2%
+ {\ifcsname\??language#1#2\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??language#1\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#2}%
+ \orelse\ifcsname\??language\s!default#2\endcsname
+ \lastnamedcs
+ \fi}
+
+\def\mainlanguageparameter#1%
+ {\ifcsname\??language\currentmainlanguage#1\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??language\currentmainlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#1}%
+ \orelse\ifcsname\??language\s!default#1\endcsname
+ \lastnamedcs
+ \fi}
+
+\let\usedlanguageparameter\languageparameter
+
+\def\askedlanguageparameter#1% assumes \currentusedlanguage being set
+ {\ifcsname\??language\currentusedlanguage#1\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??language\currentusedlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#1}%
+ \orelse\ifcsname\??language\s!default#1\endcsname
+ \lastnamedcs
+ \fi}
+
+\unexpanded\def\setusedlanguage#1%
+ {\edef\currentusedlanguage{\reallanguagetag{#1}}%
+ \ifx\currentusedlanguage\empty
+ \let\currentusedlanguage \currentlanguage
+ \let\usedlanguageparameter\languageparameter
+ \orelse\ifx\currentusedlanguage\v!global
+ \let\currentusedlanguage \currentmainlanguage
+ \let\usedlanguageparameter\mainlanguageparameter
+ \orelse\ifx\currentusedlanguage\v!local
+ \let\currentusedlanguage \currentlanguage
+ \let\usedlanguageparameter\languageparameter
+ \else
+ \let\usedlanguageparameter\askedlanguageparameter
+ \fi}
+
+\unexpanded\def\setupcurrentlanguage[#1]%
+ {\setcurrentlanguage\currentmainlanguage{#1}}
+
+\unexpanded\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
+ {\edef\xaskedlanguage{#1}% otherwise clash with \askedlanguage
+ \ifx\xaskedlanguage\empty \else
+ \ifx\currentmainlanguage\empty\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi
+ \let\currentmainlanguage\xaskedlanguage
+ \setsystemmode{\systemmodeprefix\currentmainlanguage}%
+ \fi
+ \edef\xaskedlanguage{#2}%
+ \ifx\xaskedlanguage\empty \else
+ \ifx\currentlanguage\empty\else\resetsystemmode\currentlanguage\fi
+ \let\currentlanguage\xaskedlanguage
+ \setsystemmode\currentlanguage
+ \fi}
+
+%D The internal macros will be defined later.
+
+%D \macros
+%D {installlanguage}
+%D
+%D Hyphenation patterns can only be loaded when the format file is prepared. The
+%D next macro takes care of this loading. A language is specified with
+%D
+%D \showsetup{installlanguage}
+%D
+%D When \type {state} equals \type {start}, both patterns and additional hyphenation
+%D specifications are loaded. These files are seached for in the patterns path
+%D have names like \type {lang-nl.lua}.
+%D
+%D The \type {spacing} variable specifies how the spaces after punctuation has to be
+%D handled. English is by tradition more tolerant to inter||sentence spacing than
+%D other languages.
+%D
+%D This macro also defines \type {\identifier} as a shortcut switch to the language.
+%D Furthermore the command defined as being language specific, are executed. With
+%D \type {default} we can default to another language (patterns) at format
+%D generation time. Patterns are loaded at runtime.
+
+\newtoks \everysetuplanguage
+
+\def\installedlanguages{\clf_installedlanguages}
+
+\unexpanded\def\doifelselanguage#1%
+ {\ifcsname\??language#1\c!state\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiflanguageelse\doifelselanguage
+
+\def\reallanguagetag#1%
+ {\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi}
+
+% \language[#1] gave unwanted side effect of loading language specifics
+
+\unexpanded\def\installlanguage
+ {\dodoubleargument\lang_basics_install}
+
+% \def\lang_basics_install[#1][#2]%
+% {\doifelseassignment{#2}
+% {\doifelselanguage{#1}
+% {\getparameters[\??language#1][#2]}
+% {\setvalue{\??languagelinked#1}{#1}%
+% \lang_basics_install_indeed{#1}{#1}%
+% \getparameters[\??language#1][\c!state=\v!start,#2]}%
+% \edef\currentsetuplanguage{#1}%
+% \clf_definelanguage{#1}{\specificlanguageparameter{#1}\s!default}%
+% \the\everysetuplanguage}
+% {\setvalue{\??languagelinked#1}{#2}%
+% \clf_setlanguagesynonym{#1}{#2}%
+% \lang_basics_install_indeed{#1}{#2}}}
+
+\def\lang_basics_install[#1][#2]%
+ {\ifcondition\validassignment{#2}%
+ \doifelselanguage{#1}
+ {\getparameters[\??language#1][#2]}
+ {\setvalue{\??languagelinked#1}{#1}%
+ \lang_basics_install_indeed{#1}{#1}%
+ \getparameters[\??language#1][\c!state=\v!start,#2]}%
+ \edef\currentsetuplanguage{#1}%
+ \clf_definelanguage{#1}{\specificlanguageparameter{#1}\s!default}%
+ \the\everysetuplanguage
+ \else
+ \setvalue{\??languagelinked#1}{#2}%
+ \clf_setlanguagesynonym{#1}{#2}%
+ \lang_basics_install_indeed{#1}{#2}%
+ \fi}
+
+\def\lang_basics_install_indeed#1#2%
+ {\ifcsname#1\endcsname\else\setuvalue{#1}{\lang_basics_set_current[#2]}\fi}
+
+%D When the second argument is a language identifier, a synonym is created. This
+%D feature is present because we used dutch mnemonics in the dutch version, but
+%D nowadays conform a standard.
+
+\unexpanded\def\doifelsepatterns#1%
+ {\begingroup % will change
+ \lang_basics_set_current[#1]%
+ \ifnum\normallanguage>\zerocount
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifpatternselse\doifelsepatterns
+
+%D \macros
+%D {setuplanguage}
+%D
+%D Quick and dirty, but useful:
+%D
+%D \showsetup{setuplanguage}
+%D
+%D Beware, this command can only be used when a language is installed.
+
+\unexpanded\def\setuplanguage
+ {\dodoubleempty\lang_basics_setup}
+
+\ifdefined\lang_basics_synchronize \else
+ \let\lang_basics_synchronize\relax % be nice for setups till we have one
+\fi
+
+\installmacrostack\currentlanguage
+
+\def\lang_basics_setup[#1][#2]%
+ {\ifsecondargument
+ \push_macro_currentlanguage % can be default
+ \edef\currentsetuplanguage{\reallanguagetag{#1}}%
+ \getparameters[\??language\currentsetuplanguage][#2]%
+ \the\everysetuplanguage
+ \pop_macro_currentlanguage
+ %\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default)
+ \else
+ \let\currentsetuplanguage\currentlanguage
+ \getparameters[\??language\currentsetuplanguage][#1]%
+ \the\everysetuplanguage
+ \fi
+ \lang_basics_synchronize}
+
+\appendtoks
+ \clf_unloadlanguage{\currentsetuplanguage}%
+\to \everysetuplanguage
+
+\setuplanguage
+ [\s!default]
+ [\s!patterns=,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \s!lefthyphenchar=-1,
+ \s!righthyphenchar=45,
+ % used in compound i.e. interfaced with c! and can be anything so no numbers
+ \c!lefthyphen=,
+ \c!righthyphen=-,
+ \c!hyphen=-,
+ \c!spacing=\v!packed,
+ \c!compoundhyphen=\compoundhyphen,
+ \c!rightcompoundhyphen=\compoundhyphen,
+ \c!leftcompoundhyphen=,
+ \c!midsentence=---,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!leftspeech=\languageparameter\c!leftquotation,
+ \c!middlespeech=,
+ \c!rightspeech=\languageparameter\c!rightquotation,
+ \c!limittext=\unknown,
+ \c!time={h,:,m},
+ \c!date={\v!year,\ ,\v!month,\ ,\v!day},
+ \c!text=Ag,
+ \s!font=] % \v!auto : experimental !
+
+% to be tested:
+%
+% \setuplanguage
+% [\s!default]
+% [\c!righthyphenchar="AD]
+
+%D The values \type {leftsentence} and \type {rightsentence} can be (and are) used
+%D to implement automatic subsentence boundary glyphs, like in {\fr |<|french
+%D guillemots|>|} or {\de |<|german guillemots|>|} or {\nl |<|dutch dashes|>|} like
+%D situations. Furthermore \type {leftquotation} and \type {leftquote} come into
+%D view \quotation {when we quote} or \quote {quote} something.
+
+%D \macros
+%D {currentdatespecification, currenttimespecification}
+%D
+%D Just to make things easy we can ask for the current date specification by saying:
+
+\def\currentdatespecification{\languageparameter\c!date}
+\def\currenttimespecification{\languageparameter\c!time}
+
+%D Carefull reading of these macros shows that it's legal to say
+%D
+%D \starttyping
+%D \installlanguage [du] [de]
+%D \stoptyping
+
+%D \macros
+%D {language,mainlanguage}
+%D
+%D Switching to another language (actually another hyphenation pattern) is done
+%D with:
+%D
+%D \starttyping
+%D \language[identifier]
+%D \stoptyping
+%D
+%D or with \type {\identifier}. Just to be compatible with \PLAIN\ \TEX, we still
+%D support the original meaning, so
+%D
+%D \starttyping
+%D \language=1
+%D \stoptyping
+%D
+%D is a valid operation, where the relation between number and language depends on
+%D the order in installing languages.
+%D
+%D \showsetup{language}
+%D \showsetup{mainlanguage}
+%D
+%D Both commands take a predefined language identifier as argument. We can use \type
+%D {\mainlanguage[identifier]} for setting the (indeed) main language. This is the
+%D language used for translating labels like {\em figure} and {\em table}. The main
+%D language defaults to the current language.
+
+\newtoks \everylanguage
+
+\installcorenamespace{languagenumbers}
+
+\appendtoks
+ % we need to reassign the number because new patterns can be defined later on
+ % so let's hope not that many \setups happen during a run
+ \expandafter\glet\csname\??languagenumbers\currentlanguage\endcsname\undefined
+\to \everysetuplanguage
+
+\def\lang_basics_synchronize_yes
+ {\zerocount % see below
+ \global\expandafter\chardef\csname\??languagenumbers\currentlanguage\endcsname
+ \clf_languagenumber
+ {\currentlanguage}%
+ {\defaultlanguage\currentlanguage}%
+ {\languageparameter\s!patterns}%
+ {\languageparameter\c!factor}%
+ \relax
+ \normallanguage\csname\??languagenumbers\currentlanguage\endcsname}
+
+\let\lang_basics_synchronize_nop\zerocount % not loaded anyway
+
+\letvalue{\??languagenumbers}\lang_basics_synchronize_nop % initime
+
+\appendtoks
+ \letvalue{\??languagenumbers}\lang_basics_synchronize_yes % runtime
+\to \everydump
+
+\def\lang_basics_synchronize
+ {\normallanguage\csname\??languagenumbers
+ \ifcsname\??languagenumbers\currentlanguage\endcsname
+ \currentlanguage
+ \fi
+ \endcsname
+ \relax
+ \the\everylanguage
+ \relax}
+
+\newcount\hyphenstate
+\newcount\hyphenminoffset
+
+\unexpanded\def\lesshyphens
+ {\advance\hyphenminoffset\plusone
+ \lang_basics_synchronize_min_max}
+
+\unexpanded\def\morehyphens
+ {\ifcase\hyphenminoffset \else
+ \advance\hyphenminoffset\minusone
+ \fi
+ \lang_basics_synchronize_min_max}
+
+\unexpanded\def\nohyphens % nicer for url's
+ {\ifx\dohyphens\relax
+ \unexpanded\edef\dohyphens
+ {\hyphenminoffset\the\hyphenminoffset\relax
+ \lang_basics_synchronize_min_max}%
+ \fi
+ \hyphenminoffset\plusthousand
+ \lang_basics_synchronize_min_max}
+
+\let\dohyphens\relax
+
+\unexpanded\def\lang_basics_synchronize_min_max % maybe store this at the lua end
+ {% these values are stored along with glyph nodes
+ \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax
+ \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax
+ \hyphenationmin\numexpr0\languageparameter\s!hyphenmin\relax
+ % these values are stored with the language (global!)
+ \prehyphenchar \languageparameter\s!righthyphenchar\relax
+ \posthyphenchar\languageparameter\s!lefthyphenchar \relax}
+
+\appendtoks
+ \lang_basics_synchronize_min_max
+\to \everylanguage
+
+\unexpanded\def\unhyphenated
+ {\groupedcommand{\lefthyphenmin\maxdimen}\donothing}
+
+% \appendtoks
+% \setups[\languageparameter\c!setups]%
+% \to \everylanguage
+
+%D You can setup the default language to reset settings.
+
+\appendtoks
+ \edef\currentlanguagesetups{\languageparameter\c!setups}%
+ \ifx\currentlanguagesetups\empty \else
+ \setups[\currentlanguagesetups]%
+ \fi
+\to \everylanguage
+
+% new
+
+\appendtoks
+ \usebidiparameter\languageparameter
+\to \everylanguage
+
+% this will move to core-spa !
+
+\appendtoks
+ \edef\p_spacing{\languageparameter\c!spacing}%
+ \ifx\p_spacing\v!broad
+ \nonfrenchspacing
+ \else
+ \frenchspacing
+ \fi
+\to \everylanguage
+
+% \mainlanguage[nl] \setuplanguage[nl][lefthyphen=,righthyphen=?]
+%
+% \dorecurse{100}{dit is toch wel een heel\normalhyphendiscretionary lang\normalhyphendiscretionary woord \recurselevel\ }
+% \dorecurse{100}{dit is toch wel een heellangwoord \recurselevel\ }
+
+% new experimental feature
+
+\unexpanded\def\setuplanguages
+ {\setuplanguage[\s!default]}
+
+% \setuplanguages[\s!font=\v!auto]
+% \setuplanguage[\s!default][\s!font=\v!auto]
+% \setuplanguage[nl][\s!font=\v!auto]
+
+\appendtoks
+ \edef\p_language_font{\languageparameter\s!font}%
+ \ifx\p_language_font\empty
+ \orelse\ifx\p_language_font\v!auto
+ \doaddfeature\currentlanguage
+ \else
+ \doaddfeature\p_language_font
+ \fi
+\to \everylanguage
+
+%D Fast switcher
+
+\def\lang_basics_switch_asked
+ {\ifcsname\??languagelinked\askedlanguage\endcsname
+ \edef\askedlanguage{\lastnamedcs}%
+ \ifx\currentlanguage\askedlanguage \else
+ \setcurrentlanguage\currentmainlanguage\askedlanguage
+ \lang_basics_synchronize
+ \fi
+ \fi}
+
+\unexpanded\def\uselanguageparameter#1%
+ {\edef\askedlanguage{#1\c!language}%
+ \ifx\askedlanguage\empty\else\lang_basics_switch_asked\fi}
+
+\unexpanded\def\douselanguageparameter#1% fast setter
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty\else\lang_basics_switch_asked\fi}
+
+\unexpanded\def\lang_basics_set_current[#1]%
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty\else\lang_basics_switch_asked\fi}
+
+\unexpanded\def\language
+ {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage}
+
+\let\setlanguage\language % we make these synonyms
+
+\let\patterns\gobbleoneargument
+
+\newcount\mainlanguagenumber
+
+%D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par}
+%D inside the group!
+
+\unexpanded\def\startlanguage
+ {\begingroup\language}
+
+\let\stoplanguage\endgroup
+
+\unexpanded\def\mainlanguage[#1]%
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty
+ \orelse\ifcsname\??languagelinked\askedlanguage\endcsname
+ %\edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+ \edef\askedlanguage{\lastnamedcs}%
+ \ifx\currentlanguage\askedlanguage
+ \ifx\currentmainlanguage\askedlanguage \else
+ \setcurrentlanguage\askedlanguage\askedlanguage
+ \lang_basics_synchronize
+ \fi
+ \else
+ \setcurrentlanguage\askedlanguage\askedlanguage
+ \lang_basics_synchronize
+ \fi
+ \fi
+ \mainlanguagenumber\normallanguage}
+
+\appendtoks
+ \normallanguage\mainlanguagenumber
+\to \everybeforepagebody
+
+%D Used at all?
+
+\def\splitsequence#1#2%
+ {\doifelse{#1}\v!no{#2}{\doifelse{#1}\v!yes{\languageparameter\c!limittext}{#1}}}
+
+\def\splitsymbol#1%
+ {\splitsequence{#1}{\languageparameter\c!limittext}}
+
+%D Just like with subsentence boundary symbols, quotes placement depends on the
+%D current language, therefore we show the defaults here.
+%D
+%D \def\ShowLanguageValues [#1] [#2] #3 #4
+%D {\blank
+%D \startlinecorrection
+%D \vbox\bgroup
+%D \language[#1]
+%D \midaligned{\bf#2 subsentence symbol and quotes}
+%D \framed[width=\hsize,frame=off,topframe=on,bottomframe=on,offset=.5ex]
+%D {\hfil\quotation{#3 #4}\hfil\quote{#2}\hfil
+%D \startsubsentence\startsubsentence#3\stopsubsentence#4\stopsubsentence\hfil}
+%D \egroup
+%D \stoplinecorrection
+%D \blank}
+%D
+%D \ShowLanguageValues [af] [afrikaans] afrikaanse ...
+%D \ShowLanguageValues [ca] [catalan] catalan ...
+%D \ShowLanguageValues [cs] [czech] tjechisch tex
+%D \ShowLanguageValues [cs] [slovak] slowaakse ...
+%D \ShowLanguageValues [da] [danish] deense ...
+%D \ShowLanguageValues [de] [german] duitse degelijkheid
+%D \ShowLanguageValues [en] [english] engelse humor
+%D \ShowLanguageValues [et] [estonian] ...
+%D \ShowLanguageValues [fi] [finnish] finse ...
+%D \ShowLanguageValues [fr] [french] franse slag
+%D \ShowLanguageValues [it] [italian] italiaanse ...
+%D \ShowLanguageValues [la] [latin] latijnse missen
+%D \ShowLanguageValues [nl] [dutch] nederlandse zuinigheid
+%D \ShowLanguageValues [nb] [bokmal] noorse zalm
+%D \ShowLanguageValues [nn] [nnynorsk] noorse zalm
+%D \ShowLanguageValues [pl] [polish] poolse vlag
+%D \ShowLanguageValues [pt] [portuguese] portugese ...
+%D \ShowLanguageValues [es] [spanish] spaans benauwd
+%D \ShowLanguageValues [sv] [swedish] zweedse ...
+%D \ShowLanguageValues [tr] [turkish] turks fruit
+
+%D We support a lot of languages. These are specified and loaded in separate files,
+%D according to their roots. Here we only take care of (postponed) setting of the
+%D current language.
+%D
+%D \unprotect
+%D \placetable{The germanic languages (\type{lang-ger})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!nl \NC dutch \NC germanic \NC\FR
+%D \NC \s!en \NC english \NC germanic \NC\MR
+%D \NC \s!de \NC german \NC germanic \NC\MR
+%D \NC \s!da \NC danish \NC germanic \NC\MR
+%D \NC \s!sv \NC swedish \NC germanic \NC\MR
+%D \NC \s!af \NC afrikaans \NC germanic \NC\MR
+%D \NC \s!nb \NC bokmal \NC germanic \NC\LR
+%D \NC \s!nn \NC nynorsk \NC germanic \NC\LR
+%D \HL
+%D \stoptable
+%D \protect
+%D
+%D \unprotect
+%D \placetable{The italic languages (\type{lang-ita})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!fr \NC french \NC italic \NC\FR
+%D \NC \s!ca \NC catalan \NC italic \NC\MR
+%D \NC \s!es \NC spanish \NC italic \NC\MR
+%D \NC \s!it \NC italian \NC italic \NC\MR
+%D \NC \s!la \NC latin \NC italic \NC\MR
+%D \NC \s!pt \NC portuguese \NC italic \NC\LR
+%D \HL
+%D \stoptable
+%D \protect
+%D
+%D \unprotect
+%D \placetable{The slavic languages (\type{lang-sla})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!pl \NC polish \NC slavic \NC\FR
+%D \NC \s!cs \NC czech \NC slavic \NC\MR
+%D \NC \s!sk \NC slavik \NC slavic \NC\LR
+%D \HL
+%D \stoptable
+%D \protect
+%D \unprotect
+%D
+%D \placetable{The altaic languages (\type{lang-alt})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!tr \NC turkish \NC altaic \NC\SR
+%D \HL
+%D \stoptable
+%D
+%D \placetable{The uralic languages (\type{lang-ura})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!fi \NC finnish \NC uralic \NC\SR
+%D \HL
+%D \stoptable
+%D \protect
+
+\unexpanded\def\nopatterns{\normallanguage\minusone}
+
+%D We default to the language belonging to the interface. This is one of the few
+%D places outside the interface modules where \type {\startinterface} is used.
+
+\setupcurrentlanguage[\s!en]
+
+\unexpanded\def\initializemainlanguage
+ {\mainlanguage[\currentlanguage]%
+ \showmessage\m!languages9\currentlanguage}
+
+%D New:
+
+\let\stopexceptions\relax
+
+\unexpanded\def\startexceptions
+ {\dosingleempty\lang_basics_start_exceptions}
+
+\def\lang_basics_start_exceptions[#1]#2\stopexceptions % multilingual or not?
+ {\begingroup
+ \edef\askedlanguage{\reallanguagetag{#1}}%
+ \ifx\askedlanguage\empty
+ \let\askedlanguage\currentlanguage
+ \fi
+ \clf_setlanguageexceptions{\askedlanguage}{#2}%
+ \endgroup}
+
+\unexpanded\def\hyphenation
+ {\clf_setlanguageexceptions{\currentlanguage}}
+
+%D For the moment here:
+
+\uchyph 1 % also treat uppercase
+\exhyphenchar 45 % to permit breaking at explicit hyphens
+
+%D New:
+
+\unexpanded\def\traceddiscretionary#1#2#3%
+ {\dontleavehmode
+ \discretionary{\darkred#1}{\darkgreen#2}{\darkblue#3}}
+
+\unexpanded\def\samplediscretionary
+ {\traceddiscretionary
+ {pre\clf_currentprehyphenchar}%
+ {\clf_currentposthyphenchar post}%
+ {replace}}
+
+% todo: make this configurable
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/lang-lab.mkiv b/tex/context/base/mkiv/lang-lab.mkiv
index f03d9af3a..1ae2d4c74 100644
--- a/tex/context/base/mkiv/lang-lab.mkiv
+++ b/tex/context/base/mkiv/lang-lab.mkiv
@@ -24,26 +24,23 @@
\def\sixperemspace{\normalUchar"2006}
\fi
-%D In this module we deal with language dependant labels and
-%D prefixes, like in {\em Figure~12} and {\em Chapter 1}. In
-%D this file we set the default values. Users can easily
-%D overrule these.
+%D In this module we deal with language dependant labels and prefixes, like in {\em
+%D Figure~12} and {\em Chapter 1}. In this file we set the default values. Users can
+%D easily overrule these.
%D
-%D This module is dedicated to the grandfather of Tobias
-%D Burnus, who's extensive languages oriented library helped us
-%D a lot in finding the right translations. All those labels
-%D are collected in files that reflect their common ancestor.
+%D This module is dedicated to the grandfather of Tobias Burnus, who's extensive
+%D languages oriented library helped us a lot in finding the right translations. All
+%D those labels are collected in files that reflect their common ancestor.
%D
-%D Not all languages can be satisfied with the labeling
-%D mechanism as provided here. Chinese for instance put a label
-%D in front as well as after a part number. This is why the
-%D current implementation of labels supports two labels too.
+%D Not all languages can be satisfied with the labeling mechanism as provided here.
+%D Chinese for instance put a label in front as well as after a part number. This is
+%D why the current implementation of labels supports two labels too.
%D \macros
%D {setupheadtext, setuplabeltext}
%D
-%D First we present some macros that deal with what we will
-%D call head and label texts. Such texts are defines by:
+%D First we present some macros that deal with what we will call head and label
+%D texts. Such texts are defines by:
%D
%D \showsetup{setupheadtext}
%D \showsetup{setuplabeltext}
@@ -165,8 +162,8 @@
%D \macros
%D {presetheadtext,presetlabeltext}
%D
-%D These macros enable us to automatically define head and label
-%D texts without replacing predefined ones. They are internal macros.
+%D These macros enable us to automatically define head and label texts without
+%D replacing predefined ones. They are internal macros.
\appendtoks \let\labellanguage\currentlanguage \to \everycurrentdate
@@ -301,9 +298,8 @@
%D \macros
%D {translate}
%D
-%D Sometimes macros contain language specific words that are to
-%D be typeset. Such macros can be made (more) language
-%D independant by using:
+%D Sometimes macros contain language specific words that are to be typeset. Such
+%D macros can be made (more) language independant by using:
%D
%D \showsetup{translate}
%D
@@ -313,8 +309,7 @@
%D \translate[en=something,nl=iets]
%D \stoptyping
%D
-%D which expands to {\em something} or {\em iets}, depending on
-%D de current language.
+%D which expands to {\em something} or {\em iets}, depending on de current language.
\installcorenamespace{translation}
@@ -331,8 +326,8 @@
[translation #1]%
\fi\fi}
-%D When used without argument, the last defined values are
-%D used. This enables repetitive use like
+%D When used without argument, the last defined values are used. This enables
+%D repetitive use like
%D
%D \starttyping
%D \en \translate\ means \nl \translate
@@ -341,8 +336,8 @@
%D \macros
%D {assigntranslation}
%D
-%D This macro is a system macro, and can be used to assign a
-%D translation to a macro. Its form is:
+%D This macro is a system macro, and can be used to assign a translation to a macro.
+%D Its form is:
%D
%D \starttyping
%D \assigntranslation[en=something,nl=iets]\to\command
diff --git a/tex/context/base/mkiv/lang-lab.mkxl b/tex/context/base/mkiv/lang-lab.mkxl
new file mode 100644
index 000000000..a527224e9
--- /dev/null
+++ b/tex/context/base/mkiv/lang-lab.mkxl
@@ -0,0 +1,390 @@
+%D \module
+%D [ file=lang-lab,
+%D version=1997.08.27,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Labels,
+%D author=Hans Hagen / Tobias Burnus,
+%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.
+
+\writestatus{loading}{ConTeXt Language Macros / Labels}
+
+\registerctxluafile{lang-lab}{}
+\registerctxluafile{lang-txt}{}
+
+\unprotect
+
+%D Left-overs:
+
+\ifdefined\sixperemspace \else
+ \def\sixperemspace{\normalUchar"2006}
+\fi
+
+%D In this module we deal with language dependant labels and prefixes, like in {\em
+%D Figure~12} and {\em Chapter 1}. In this file we set the default values. Users can
+%D easily overrule these.
+%D
+%D This module is dedicated to the grandfather of Tobias Burnus, who's extensive
+%D languages oriented library helped us a lot in finding the right translations. All
+%D those labels are collected in files that reflect their common ancestor.
+%D
+%D Not all languages can be satisfied with the labeling mechanism as provided here.
+%D Chinese for instance put a label in front as well as after a part number. This is
+%D why the current implementation of labels supports two labels too.
+
+%D \macros
+%D {setupheadtext, setuplabeltext}
+%D
+%D First we present some macros that deal with what we will call head and label
+%D texts. Such texts are defines by:
+%D
+%D \showsetup{setupheadtext}
+%D \showsetup{setuplabeltext}
+%D
+%D A regular \CONTEXT\ stores some 1500 labels at most.
+%D
+%D These commands accept all kind of inputs:
+%D
+%D \starttyping
+%D \setuplabeltext [language] [labellabel=text]
+%D \setuplabeltext [language] [labellabel=text,labellabel=text,...]
+%D \setuplabeltext [labellabel=text]
+%D \setuplabeltext [labellabel=text,labellabel=text,...]
+%D \stoptyping
+%D
+%D The last two cases concern the current language.
+
+\installcorenamespace{label}
+
+\let\currentlabelcategory\empty
+
+\unexpanded\def\definelabelclass
+ {\dodoubleempty\lang_labels_define_class}
+
+\def\lang_labels_define_class[#1][#2]%
+ {\normalexpanded
+ {\lang_labels_define_class_indeed
+ {#1}%
+ {\ifsecondargument#2\else\zerocount\fi}%
+ \expandafter\noexpand\csname dogetupsome#1text\endcsname
+ \expandafter\noexpand\csname #1language\endcsname
+ \expandafter\noexpand\csname dodogetupsome#1text\endcsname
+ \expandafter\noexpand\csname left#1text\endcsname
+ \expandafter\noexpand\csname right#1text\endcsname
+ \expandafter\noexpand\csname #1texts\endcsname
+ \expandafter\noexpand\csname #1text\endcsname}}
+
+% hm, not interfaced
+
+\let\thetextprefix\empty
+
+\unexpanded\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9%
+ {\setuvalue{setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}%
+ \setuvalue{preset#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}%
+ \setuvalue{copy#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_copy}%
+ \setuvalue{start#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dotripleempty\lang_labels_text_prefix_start[#1]}%
+ \letvalue{stop#1text}\relax
+ \def#4{\reallanguagetag{\defaultlanguage\currentmainlanguage}}%
+ \ifnum#2=\plustwo % used for math and tags
+ \def#3{#5#4}%
+ \def#5##1##2% ##1=language
+ {\ifcsname\??label\currentlabelcategory#1:##1:##2\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??label#1:##1:##2\endcsname
+ \lastnamedcs
+ % \orelse\ifcsname\??language#4\s!default\endcsname
+ % \expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+ \orelse\ifcsname\??language##1\s!default\endcsname
+ %\expandafter#5\csname\??language##1\s!default\endcsname{##2}%
+ \expandafter#5\lastnamedcs{##2}%
+ \orelse\ifcsname\??label\currentlabelcategory#1:##2\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??label#1:##2\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??label\currentlabelcategory#1:\s!en:##2\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??label#1:\s!en:##2\endcsname
+ \lastnamedcs
+ \else
+ ##2%
+ \fi}%
+ \let#6\gobbleoneargument
+ \let#7\gobbleoneargument
+ \let#8\gobbletwoarguments
+ \let#9#3%
+ \else
+ \unexpanded\def#3{#5#4}%
+ \unexpanded\def#5##1##2%
+ {\ifcsname\??label#1:##1:##2\endcsname
+ %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##1:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \orelse\ifcsname\??language#4\s!default\endcsname
+ %\expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+ \expandafter#5\lastnamedcs{##2}%
+ \orelse\ifcsname\??label#1:##2\endcsname
+ %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \orelse\ifcsname\??label#1:\s!en:##2\endcsname
+ %\expandafter\let\expandafter\thetextprefix\csname\??label#1:\s!en:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \else
+ \let\thetextprefix\dummytextprefix
+ \fi}%
+ \unexpanded\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
+ \unexpanded\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}%
+ \unexpanded\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2
+ \unexpanded\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
+ \fi
+ \appendtoks
+ \let#6\firstofoneargument % to be checked
+ \let#7\firstofoneargument % to be checked
+ \let#8\firstofoneargument % to be checked
+ \let#9\firstofoneargument % to be checked
+ \to \everysimplifycommands}
+
+\let\flushleftlabelclass \firstoftwoarguments
+\let\flushrightlabelclass\secondoftwoarguments
+\def\flushbothlabelclass #1#2#3{#1#3#2}
+\def\dummytextprefix {\empty\empty}
+
+%D \macros
+%D {headtext, labeltext, leftlabeltext, rightlabeltext, labeltexts}
+%D
+%D Once defined, head and label texts can be called upon using:
+%D
+%D \showsetup{headtext}
+%D \showsetup{labeltext}
+%D
+%D \macros
+%D {presetheadtext,presetlabeltext}
+%D
+%D These macros enable us to automatically define head and label texts without
+%D replacing predefined ones. They are internal macros.
+
+\appendtoks \let\labellanguage\currentlanguage \to \everycurrentdate
+
+\newconstant\protecttextprefixes
+
+\let\currenttextprefixtag \s!unknown
+\let\currenttextprefixclass\s!unknown
+
+\def\lang_labels_text_prefix_start[#1][#2][#3]% class language name
+ {\ifthirdargument
+ \edef\currenttextprefixtag{\reallanguagetag{#2}}%
+ \edef\currenttextprefixname{#3}%
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \edef\currenttextprefixname{#2}%
+ \fi
+ \grabuntil{stop#1text}\lang_labels_text_prefix_start_indeed}
+
+\def\lang_labels_text_prefix_start_indeed#1% text (not special checking done here yet, only for long texts anyway)
+ {\expandafter\edef\csname\??label\currenttextprefixclass:\currenttextprefixtag:\currenttextprefixname\endcsname%
+ {{\clf_strip{#1}}\empty}}
+
+\def\lang_labels_text_prefix_setup[#1][#2]%
+ {\ifsecondargument
+ \edef\currenttextprefixtag{\reallanguagetag{#1}}%
+ \processcommalist[#2]\lang_labels_text_prefix_setup_indeed
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \processcommalist[#1]\lang_labels_text_prefix_setup_indeed
+ \fi}
+
+\def\lang_labels_text_prefix_setup_indeed#1%
+ {\lang_labels_text_prefix_assign[#1]}
+
+\def\lang_labels_text_prefix_assign[#1=#2]%
+ {\lang_labels_text_prefix_assign_indeed{#1}[#2,,]}
+
+\def\lang_labels_text_prefix_assign_indeed#1%
+ {\ifcase\protecttextprefixes
+ % no checking
+ \expandafter\lang_labels_text_prefix_assign_yes
+ \or
+ % checking
+ \ifcsname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname
+ \expandafter\expandafter\expandafter\lang_labels_text_prefix_assign_nop
+ \else
+ \expandafter\expandafter\expandafter\lang_labels_text_prefix_assign_yes
+ \fi
+ \or
+ % simple assignment (a bit overkill but it fits in the whole)
+ \expandafter\lang_labels_text_prefix_assign_dumb
+ \fi{#1}}
+
+\let\m_lang_labels_left \empty
+\let\m_lang_labels_right\empty
+
+% \def\lang_labels_text_prefix_assign_yes#1[#2,#3,#4]%
+% {\def\m_lang_labels_left {#2}% no longer an edef ... else \Word undefined expansion issues
+% \def\m_lang_labels_right{#3}% no longer an edef ... else \Word undefined expansion issues
+% \ifx\m_lang_labels_right\empty
+% \ifx\m_lang_labels_left\empty
+% \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{\empty\empty}%
+% \else
+% \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}\empty}%
+% \fi
+% \else
+% \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}{#3}}%
+% \fi}
+%
+% how we love obscure efficicency ...
+
+\def\lang_labels_text_prefix_assign_yes#1[#2,#3,#4]%
+ {\def\m_lang_labels_left {#2}% no longer an edef ... else \Word undefined expansion issues
+ \def\m_lang_labels_right{#3}% no longer an edef ... else \Word undefined expansion issues
+ \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1%
+ \ifx\m_lang_labels_right\empty
+ \ifx\m_lang_labels_left\empty
+ \endcsname{\empty\empty}%
+ \else
+ \endcsname{{#2}\empty}%
+ \fi
+ \else
+ \endcsname{{#2}{#3}}%
+ \fi}
+
+\def\lang_labels_text_prefix_assign_nop#1[#2]%
+ {}
+
+\def\lang_labels_text_prefix_assign_dumb#1[#2,#3]%
+ {\expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}}
+
+\unexpanded\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end
+ {%\writestatus{!!!!}{#1:\reallanguagetag{#2}:#3}%
+ \expandafter\def\csname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right
+
+\def\lang_labels_text_prefix_copy[#1][#2]%
+ {\ifsecondargument
+ \edef\currenttextprefixtag{\reallanguagetag{#1}}%
+ \processcommalist[#2]\lang_labels_text_prefix_copy_indeed
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \processcommalist[#1]\lang_labels_text_prefix_copy_indeed
+ \fi}
+
+\def\lang_labels_text_prefix_copy_indeed#1%
+ {\lang_labels_text_prefix_copy_pair[#1]}
+
+\def\lang_labels_text_prefix_copy_pair[#1=#2]%
+ {\lang_labels_text_prefix_copy_pair_indeed{#1}[#2,,]}
+
+% \def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]%
+% {\expandafter\let
+% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\expandafter\endcsname
+% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#2\endcsname}
+%
+% this delays the aliasing so that we can switch maillanguage in between
+
+\def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]%
+ {\expandafter\edef\csname\??label\currenttextprefixclass:#1\endcsname
+ {{\noexpand\csname\??label\currenttextprefixclass:\noexpand\reallanguagetag\noexpand\currentmainlanguage:#2\endcsname}{}}}
+
+\definelabelclass [head] [0] % titles
+\definelabelclass [label] [0] % texts
+\definelabelclass [mathlabel] [0] % functions
+\definelabelclass [taglabel] [2] % tags
+
+\clf_definelabels{head}{titles}\s!true\relax
+\clf_definelabels{label}{texts}\s!true\relax
+\clf_definelabels{mathlabel}{functions}\s!false\relax
+\clf_definelabels{taglabel}{tags}\s!false\relax
+
+%D \macros
+%D {translate}
+%D
+%D Sometimes macros contain language specific words that are to be typeset. Such
+%D macros can be made (more) language independant by using:
+%D
+%D \showsetup{translate}
+%D
+%D like for instance:
+%D
+%D \starttyping
+%D \translate[en=something,nl=iets]
+%D \stoptyping
+%D
+%D which expands to {\em something} or {\em iets}, depending on de current language.
+
+\installcorenamespace{translation}
+
+\unexpanded\def\translate
+ {\dosingleempty\lang_translate}
+
+\def\lang_translate[#1]%
+ {\getparameters[\??translation][#1]%
+ \ifcsname\??translation\currentlanguage\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??translation\s!en\endcsname
+ \lastnamedcs
+ \else
+ [translation #1]%
+ \fi}
+
+%D When used without argument, the last defined values are used. This enables
+%D repetitive use like
+%D
+%D \starttyping
+%D \en \translate\ means \nl \translate
+%D \stoptyping
+
+%D \macros
+%D {assigntranslation}
+%D
+%D This macro is a system macro, and can be used to assign a translation to a macro.
+%D Its form is:
+%D
+%D \starttyping
+%D \assigntranslation[en=something,nl=iets]\to\command
+%D \stoptyping
+
+\unexpanded\def\assigntranslation[#1]\to#2% bad, this \to
+ {\getparameters[\??translation][#1]%
+ \edef#2{\begincsname\??translation\currentlanguage\endcsname}}
+
+%D \macros
+%D {commalistsentence}
+%D
+%D Redone in \LUA:
+%D
+%D \startbuffer
+%D \commalistsentence[aap,noot,mies]
+%D \commalistsentence[aap,noot]
+%D \commalistsentence[aap]
+%D \commalistsentence[a,b,c]
+%D \commalistsentence[a,b,c][{ \& },{ and }]
+%D \commalistsentence[a,b,c][+,-]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\unexpanded\def\commalistsentence
+ {\dodoubleempty\typo_helpers_concat_comma_list}
+
+\def\typo_helpers_concat_comma_list[#1][#2]%
+ {\clf_concatcommalist
+ text {#1}%
+ separators {#2}%
+ separator {\detokenize\expandafter{\normalexpanded{\labeltext{and-1}}}}%
+ last {\detokenize\expandafter{\normalexpanded{\labeltext{and-2}}}}%
+ \relax}
+
+\setuplabeltext [\s!nl] [and-1={{, }}, and-2={{ en }}] % 1, 2 en 3
+\setuplabeltext [\s!en] [and-1={{, }}, and-2={{, }}] % 1, 2, 3
+\setuplabeltext [\s!de] [and-1={{, }}, and-2={{ und }}] % 1, 2 und 3
+\setuplabeltext [\s!hr] [and-1={{, }}, and-2={{ i }}] % 1, 2 i 3
+
+%D Goodie (handy at \LUA\ end):
+
+\unexpanded\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases!
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/lpdf-eng.lua b/tex/context/base/mkiv/lpdf-eng.lua
index 42435fad5..21c7e66e9 100644
--- a/tex/context/base/mkiv/lpdf-eng.lua
+++ b/tex/context/base/mkiv/lpdf-eng.lua
@@ -6,10 +6,6 @@ if not modules then modules = { } end modules ['lpdf-eng'] = {
license = "see context related readme files"
}
-if CONTEXTLMTXMODE > 0 then
- return
-end
-
-- Here we plug in the regular luatex image handler. The low level module itself
-- is hidden from the user.
diff --git a/tex/context/base/mkiv/lpdf-lmt.lua b/tex/context/base/mkiv/lpdf-lmt.lua
index 8fdbf9a36..5d8ad063c 100644
--- a/tex/context/base/mkiv/lpdf-lmt.lua
+++ b/tex/context/base/mkiv/lpdf-lmt.lua
@@ -18,10 +18,6 @@ if not modules then modules = { } end modules ['lpdf-lmt'] = {
-- Thomas's turture test (also for other reasons). But .. who knows what magic
-- I can cook up in due time.
-if CONTEXTLMTXMODE == 0 then
- return
-end
-
-- If you consider this complex, watch:
--
-- https://www.youtube.com/watch?v=6H-cAzfB2qo
diff --git a/tex/context/base/mkiv/lpdf-nod.lua b/tex/context/base/mkiv/lpdf-nod.lua
index db99f0e5d..fcb2d1457 100644
--- a/tex/context/base/mkiv/lpdf-nod.lua
+++ b/tex/context/base/mkiv/lpdf-nod.lua
@@ -6,10 +6,6 @@ if not modules then modules = { } end modules ['lpdf-nod'] = {
license = "see context related readme files"
}
-if CONTEXTLMTXMODE > 0 then
- return
-end
-
local nodecodes = nodes.nodecodes
local whatsitcodes = nodes.whatsitcodes
diff --git a/tex/context/base/mkiv/luat-env.lua b/tex/context/base/mkiv/luat-env.lua
index e0c69d207..e6a0c8c5d 100644
--- a/tex/context/base/mkiv/luat-env.lua
+++ b/tex/context/base/mkiv/luat-env.lua
@@ -71,6 +71,17 @@ function environment.texfile(filename)
end
function environment.luafile(filename) -- needs checking
+
+ if CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and file.suffix(filename) == "lua" then
+ -- no "tex", as that's pretty slow when not found (suffixes get appended, shouldn't happen)
+ -- trackers.enable("resolvers.*")
+ local resolved = resolvers.findfile(file.replacesuffix(filename,"lmt")) or ""
+ -- trackers.disable("resolvers.*")
+ if resolved ~= "" then
+ return resolved
+ end
+ end
+
local resolved = resolvers.findfile(filename,'tex') or ""
if resolved ~= "" then
return resolved
diff --git a/tex/context/base/mkiv/luat-fmt.lua b/tex/context/base/mkiv/luat-fmt.lua
index 586c5948e..86cf5cf9e 100644
--- a/tex/context/base/mkiv/luat-fmt.lua
+++ b/tex/context/base/mkiv/luat-fmt.lua
@@ -107,8 +107,16 @@ function environment.make_format(name,arguments)
end
report_format("using format path %a",dir.current())
-- check source file
- local texsourcename = file.addsuffix(name,"mkiv")
- local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
+ local texsourcename = ""
+ local fulltexsourcename = ""
+ if engine == "luametatex" then
+ texsourcename = file.addsuffix(name,"mkxl")
+ fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
+ end
+ if fulltexsourcename == "" then
+ texsourcename = file.addsuffix(name,"mkiv")
+ fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
+ end
if fulltexsourcename == "" then
texsourcename = file.addsuffix(name,"tex")
fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv
index 381a60e42..5b14b1d11 100644
--- a/tex/context/base/mkiv/luat-lib.mkiv
+++ b/tex/context/base/mkiv/luat-lib.mkiv
@@ -19,18 +19,13 @@
\registerctxluafile{util-sac}{optimize}
\registerctxluafile{util-sto}{} % could also be done in trac-deb.mkiv
\registerctxluafile{util-pck}{}
-% \registerctxluafile{util-seq}{}
-%registerctxluafile{util-mrg}{} % not needed in context itself, only mtxrun
-%registerctxluafile{util-lua}{} % moved
\registerctxluafile{util-prs}{}
\registerctxluafile{util-fmt}{}
\registerctxluafile{util-dim}{}
-%registerctxluafile{trac-inf}{}
\registerctxluafile{trac-set}{}
\registerctxluafile{trac-log}{}
\registerctxluafile{trac-inf}{}
-%registerctxluafile{trac-pro}{}
\registerctxluafile{util-lua}{}
\registerctxluafile{util-deb}{} % could also be done in trac-deb.mkiv
@@ -43,16 +38,12 @@
\registerctxluafile{util-soc-imp-reset} {}
\registerctxluafile{util-soc-imp-socket} {}
-%registerctxluafile{util-soc-imp-copas} {}
\registerctxluafile{util-soc-imp-ltn12} {}
-%registerctxluafile{util-soc-imp-mbox} {}
\registerctxluafile{util-soc-imp-mime} {}
\registerctxluafile{util-soc-imp-url} {}
\registerctxluafile{util-soc-imp-headers}{}
\registerctxluafile{util-soc-imp-http} {}
\registerctxluafile{util-soc-imp-tp} {}
-%registerctxluafile{util-soc-imp-ftp} {}
-%registerctxluafile{util-soc-imp-smtp} {}
\ifcase\contextlmtxmode\else
\registerctxluafile{util-zip}{}
diff --git a/tex/context/base/mkiv/luat-mac.lua b/tex/context/base/mkiv/luat-mac.lua
index cc1ee67f2..91148bc32 100644
--- a/tex/context/base/mkiv/luat-mac.lua
+++ b/tex/context/base/mkiv/luat-mac.lua
@@ -337,8 +337,8 @@ if resolvers.schemes then
return cachename
end
- resolvers.schemes.install('mkvi',handler,1) -- this will cache !
- resolvers.schemes.install('mklx',handler,1) -- bonus, best use just mkvi
+ resolvers.schemes.install('mkvi',handler,1)
+ resolvers.schemes.install('mklx',handler,1)
end
diff --git a/tex/context/base/mkiv/meta-imp-dum.mkiv b/tex/context/base/mkiv/meta-imp-dum.mkiv
index b84d4ac7a..457de4b35 100644
--- a/tex/context/base/mkiv/meta-imp-dum.mkiv
+++ b/tex/context/base/mkiv/meta-imp-dum.mkiv
@@ -30,69 +30,70 @@
%D
%D \typebuffer \getbuffer
-% currently preparempvariables is unable to resolve number
-% fractions like reduction
-
-% June 22, 2003, this definition was patched to adapt itself
-% to transparent colors, but ... in 2011 we no longer have
-% is_transparent so we revert.
-%
-% \startuseMPgraphic{placeholder}{width,height,reduction,color}
-% numeric w, h, d, r ; color c, b, cc ; path p ; boolean t ;
-% t := is_transparent(\MPvar{color}) ;
-% c := not_transparent(\MPvar{color}) ;
-% b := not_transparent(white) ;
-% w := \MPvar{width} ;
-% h := \MPvar{height} ;
-% r := \MPvar{reduction} ;
-% d := max(w,h) ;
-% p := unitsquare xyscaled (w,h) ;
-% cc := r[.5c,b] ;
-% fill p withcolor if t : transparent(1,.5,cc) else : cc fi ;
-% for i := 1 upto 60 :
-% cc := r[c randomized(.3,.9),b] ;
-% fill fullcircle
-% scaled (d/5 randomized (d/5))
-% shifted (center p randomized (d))
-% withcolor if t : transparent(1,.5,cc) else : cc fi ;
-% endfor ;
-% clip currentpicture to p ;
-% \stopuseMPgraphic
-
-\startuseMPgraphic{minifun::figure:placeholder}{width,height,reduction,color}
- begingroup ;
- save w, h, d, r, p, c, b ;
- numeric w, h, d, r ; path p ;
- if cmykcolor \MPvar{color} :
- cmykcolor c, b ; b := (0,0,0,0)
- else :
- color c, b ; b := (1,1,1)
- fi ;
- c := \MPvar{color} ;
- w := \MPvar{width} ;
- h := \MPvar{height} ;
- r := \MPvar{reduction} ;
- d := max(w,h) ;
- p := unitsquare xyscaled (w,h) ;
- fill p withcolor r[.5c,b] ;
- for i := 1 upto 60 :
- fill fullcircle
- scaled (d/5 randomized (d/5))
- shifted (center p randomized (d))
- withcolor r[c randomized(.3,.9),b] ;
- endfor ;
- clip currentpicture to p ;
- endgroup ;
-\stopuseMPgraphic
-
-\defineoverlay
- [figure:placeholder:graphic]
- [\useMPgraphic
- {minifun::figure:placeholder}%
- {width=\figurewidth,%
- height=\figureheight,%
- reduction=\externalfigureparameter\c!reduction,%
- color=placeholder:\the\c_grph_replacement_n}] % weird, why do we need to prefix the palette
+\startmkivmode
+
+%D Currently preparempvariables is unable to resolve number fractions like
+%D reduction.
+
+ \startuseMPgraphic{minifun::figure:placeholder}{width,height,reduction,color}
+ begingroup ;
+ save w, h, d, r, p, c, b ;
+ numeric w, h, d, r ; path p ;
+ if cmykcolor \MPvar{color} :
+ cmykcolor c, b ; b := (0,0,0,0)
+ else :
+ color c, b ; b := (1,1,1)
+ fi ;
+ c := \MPvar{color} ;
+ w := \MPvar{width} ;
+ h := \MPvar{height} ;
+ r := \MPvar{reduction} ;
+ d := max(w,h) ;
+ p := unitsquare xyscaled (w,h) ;
+ fill p withcolor r[.5c,b] ;
+ for i := 1 upto 60 :
+ fill fullcircle
+ scaled (d/5 randomized (d/5))
+ shifted (center p randomized (d))
+ withcolor r[c randomized(.3,.9),b] ;
+ endfor ;
+ clip currentpicture to p ;
+ endgroup ;
+ \stopuseMPgraphic
+
+ \defineoverlay
+ [figure:placeholder:graphic]
+ [\useMPgraphic
+ {minifun::figure:placeholder}%
+ {width=\figurewidth,%
+ height=\figureheight,%
+ reduction=\externalfigureparameter\c!reduction,%
+ color=placeholder:\the\c_grph_replacement_n}] % weird, why do we need to prefix the palette
+
+\stopmkivmode
+
+\startlmtxmode
+
+ \defineMPparameterset
+ [placeholder]
+ [width=dimension,
+ height=dimension,
+ reduction=number,
+ color=string,
+ alternative=string]
+
+ \defineoverlay
+ [figure:placeholder:graphic]
+ [{\useMPmacro
+ [minifun]%
+ [placeholder]%
+ [width=\figurewidth,%
+ height=\figureheight,%
+ alternative=\externalfigureparameter\c!alternative,
+ reduction=\externalfigureparameter\c!reduction,%
+ color=placeholder:\the\c_grph_replacement_n]}]
+
+\stoplmtxmode
\definepalet
[placeholder]
diff --git a/tex/context/base/mkiv/meta-mac.mkxl b/tex/context/base/mkiv/meta-mac.mkxl
new file mode 100644
index 000000000..3bf38b4c8
--- /dev/null
+++ b/tex/context/base/mkiv/meta-mac.mkxl
@@ -0,0 +1,66 @@
+%D \module
+%D [ file=meta-scn,
+%D version=2019.07.19,
+%D title=\METAPOST\ Graphics,
+%D subtitle=LMTX support,
+%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.
+
+\unprotect
+
+\unexpanded\def\defineMPparameterset[#1]{\clf_lmt_parameters_define{#1}}
+\unexpanded\def\presetMPparameters [#1]{\clf_lmt_parameters_preset{#1}}
+\unexpanded\def\resetMPparameters [#1]{\clf_lmt_parameters_reset {#1}}
+
+% \unexpanded\def\useMPgraphic
+% {\doifnextoptionalelse\meta_use_MP_graphic_yes\meta_use_MP_graphic_nop}
+
+% \def\meta_use_MP_graphic_nop
+% {\dodoublegroupempty\meta_use_graphic}
+
+% \def\meta_use_MP_graphic_yes
+% {\dodoubleempty\meta_use_graphic_new}
+
+% \def\meta_use_graphic_new[#1][#2]%
+% {\begingroup
+% % If really needed weh can use grouplevel but normally these graphics are
+% % not nested.
+% \clf_lmt_parameters_preset{#1}[#2]%
+% \meta_use_graphic{#1}{}%
+% \clf_lmt_parameters_reset{#1}%
+% \endgroup}
+
+\unexpanded\def\useMPmacro
+ {\dotripleempty\meta_use_macro}
+
+\def\meta_use_macro[#1][#2][#3]%
+ {\ifthirdargument
+ \meta_begin_graphic_group{#1}%
+ \meta_enable_include
+ \clf_lmt_parameters_preset{#2}[#3]%
+ \meta_process_graphic{lmt_#2;}%
+ \clf_lmt_parameters_reset{#2}%
+ \meta_end_graphic_group
+ \else\ifsecondargument
+ \doifelseassignment{#2}
+ {\let\currentMPinstance\defaultMPinstance
+ \meta_enable_include
+ \clf_lmt_parameters_preset{#1}[#2]%
+ \meta_process_graphic{lmt_#1;}%
+ \clf_lmt_parameters_reset{#1}}%
+ {\meta_begin_graphic_group{#1}%
+ \meta_enable_include
+ \meta_process_graphic{lmt_#1;}%
+ \meta_end_graphic_group}%
+ \else
+ \let\currentMPinstance\defaultMPinstance
+ \meta_enable_include
+ \meta_process_graphic{lmt_#1;}%
+ \fi\fi}
+
+\protect
diff --git a/tex/context/base/mkiv/mlib-ctx.mkiv b/tex/context/base/mkiv/mlib-ctx.mkiv
index cb925ec9b..145cdb261 100644
--- a/tex/context/base/mkiv/mlib-ctx.mkiv
+++ b/tex/context/base/mkiv/mlib-ctx.mkiv
@@ -11,83 +11,14 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This file contains the \MPLIB\ variants of the by now ancient
-%D \MPTOPDF\ code.
-
\writestatus{loading}{MetaPost Library Graphics / Initializations}
\registerctxluafile{mlib-run}{}
\registerctxluafile{mlib-ctx}{}
\registerctxluafile{mlib-lua}{}
-
-\startlmtxmode
- \doifelsefileexists{mlib-scn.lua} {
- \registerctxluafile{mlib-scn}{}
- } {
- % experimental code for Alan and me
- }
-\stoplmtxmode
-
\registerctxluafile{mlib-lmp}{}
\registerctxluafile{mlib-int}{}
\unprotect
\protect \endinput
-
-% local mpgraphic = [[
-% for i=1 upto 1000 :
-% beginfig(0);
-% draw halfcircle scaled 1cm withcolor green ;
-% picture p ; p := "oeps" infont defaultfont scaled .75 rotated 45 ;
-% p := p shifted - (xpart center p,0) ;
-% draw p ; draw boundingbox p ;
-% endfig ;
-% beginfig(0);
-% draw halfcircle scaled 1cm dashed evenly withcolor green ;
-% endfig ;
-% beginfig(0);
-% pickup pencircle xscaled .5mm yscaled .25mm rotated 45 ;
-% draw halfcircle scaled 1cm withcolor red ;
-% endfig ;
-% beginfig(0);
-% draw halfcircle scaled 1cm ;
-% endfig ;
-% beginfig(0);
-% pickup pencircle xscaled .5mm yscaled .25mm rotated 45 ;
-% for k:=1 upto 10 :
-% draw halfcircle scaled uniformdeviate(1cm) withcolor (red/(k/4)) ;
-% endfor ;
-% endfig ;
-% endfor ;
-% ]]
-% -- local mpx = metapost.format("metafun")
-% metapost.process(metapost.format("metafun"),mpgraphic)
-
-% \starttext
-% \setupcolors[state=start]
-% \definecolor[red] [r=1]
-% \definecolor[cyan][c=1]
-% \setbox\scratchbox\hbox{\startMPcode\stopMPcode} % first specials are forgotten
-% \definecolor[sss][t=.5,a=1,r=1]
-% \definespotcolor[oeps1][green][p=.5]
-% \definespotcolor[oeps2][green][p=.25]
-% \definespotcolor[oeps3][green][p=.25,t=.5,a=1]
-% \startMPpage
-% fill fullcircle scaled 10cm withcolor \MPcolor{red} ;
-% fill fullcircle scaled 8cm withcolor cmyk(1,0,0,0) ;
-% fill fullcircle scaled 6cm withcolor cmyk(0,1,0,0) ;
-% fill fullcircle scaled 4cm withcolor cmyk(0,0,1,0) ;
-% fill fullcircle scaled 2cm withcolor cmyk(0,0,0,1) ;
-% currentpicture := currentpicture shifted (-7.5cm,0) ;
-% fill fullcircle scaled 10cm withcolor transparent(1,0.75,cmyk(0,0,1,0)) ;
-% fill fullcircle scaled 8cm withcolor \MPcolor{sss} ;
-% fill fullcircle scaled 6cm withcolor \MPcolor{oeps1} ;
-% fill fullcircle scaled 4cm withcolor \MPcolor{oeps2} ;
-% currentpicture := currentpicture shifted (-7.5cm,0) ;
-% fill fullcircle scaled 10cm withcolor \MPcolor{oeps3} ;
-% circular_shade(fullcircle scaled 8cm, 1, red, blue) ;
-% circular_shade(fullcircle scaled 6cm, 1, (1,0,0,0), (0,1,0,0)) ;
-% circular_shade(fullcircle scaled 4cm, 1, cmyk(.5,.5,1,0), (0,1,0,0)) ;
-% \stopMPpage
-% \stoptext
diff --git a/tex/context/base/mkiv/mlib-ctx.mkxl b/tex/context/base/mkiv/mlib-ctx.mkxl
new file mode 100644
index 000000000..56b8587a8
--- /dev/null
+++ b/tex/context/base/mkiv/mlib-ctx.mkxl
@@ -0,0 +1,27 @@
+%D \module
+%D [ file=mlib-ctx,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Basics,
+%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.
+
+\writestatus{loading}{MetaPost Library Graphics / Initializations}
+
+\registerctxluafile{mlib-run}{}
+\registerctxluafile{mlib-ctx}{}
+\registerctxluafile{mlib-lua}{}
+\registerctxluafile{mlib-scn}{}
+\registerctxluafile{mlib-mat}{}
+\registerctxluafile{mlib-lmp}{}
+\registerctxluafile{mlib-int}{}
+
+\unprotect
+
+\protect \endinput
+
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index 8310a2925..a3e5e84cd 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -62,12 +62,14 @@ do
local stack = { }
local get_numeric = mplib.get_numeric
+ local get_integer = mplib.get_integer
local get_string = mplib.get_string
local get_boolean = mplib.get_boolean
local get_path = mplib.get_path
get.numeric = function(s) return get_numeric(currentmpx,s) end
get.number = function(s) return get_numeric(currentmpx,s) end
+ get.integer = function(s) return get_integer(currentmpx,s) end
get.string = function(s) return get_string (currentmpx,s) end
get.boolean = function(s) return get_boolean(currentmpx,s) end
get.path = function(s) return get_path (currentmpx,s) end
@@ -81,6 +83,7 @@ do
local scan_token = mplib.scan_token
local scan_symbol = mplib.scan_symbol
local scan_numeric = mplib.scan_numeric
+ local scan_integer = mplib.scan_integer
local scan_boolean = mplib.scan_boolean
local scan_string = mplib.scan_string
local scan_pair = mplib.scan_pair
@@ -95,6 +98,7 @@ do
scan.symbol = function(k) return scan_symbol (currentmpx,k) end
scan.numeric = function() return scan_numeric (currentmpx) end
scan.number = function() return scan_numeric (currentmpx) end
+ scan.integer = function() return scan_integer (currentmpx) end
scan.boolean = function() return scan_boolean (currentmpx) end
scan.string = function() return scan_string (currentmpx) end
scan.pair = function(t) return scan_pair (currentmpx,t) end
diff --git a/tex/context/base/mkiv/mlib-mat.lua b/tex/context/base/mkiv/mlib-mat.lua
new file mode 100644
index 000000000..4646a8979
--- /dev/null
+++ b/tex/context/base/mkiv/mlib-mat.lua
@@ -0,0 +1,133 @@
+if not modules then modules = { } end modules ['mlib-mat'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local scanners = mp.scan
+local registerscript = metapost.registerscript
+
+local scannumeric = scanners.numeric
+local scanpair = scanners.pair
+local scancolor = scanners.color
+
+local mppair = mp.pair
+
+local m = xmath
+local c = xcomplex
+
+local m_acos = m.acos registerscript("m_acos", function() return m_acos (scannumeric()) end)
+local m_acosh = m.acosh registerscript("m_acosh", function() return m_acosh (scannumeric()) end)
+local m_asin = m.asin registerscript("m_asin", function() return m_asin (scannumeric()) end)
+local m_asinh = m.asinh registerscript("m_asinh", function() return m_asinh (scannumeric()) end)
+local m_atan = m.atan registerscript("m_atan", function() return m_atan (scannumeric()) end)
+local m_atan2 = m.atan2 registerscript("m_atan2", function() return m_atan2 (scanpair ()) end)
+local m_atanh = m.atanh registerscript("m_atanh", function() return m_atanh (scannumeric()) end)
+local m_cbrt = m.cbrt registerscript("m_cbrt", function() return m_cbrt (scannumeric()) end)
+local m_ceil = m.ceil registerscript("m_ceil", function() return m_ceil (scannumeric()) end)
+local m_copysign = m.copysign registerscript("m_copysign", function() return m_copysign (scanpair ()) end)
+local m_cos = m.cos registerscript("m_cos", function() return m_cos (scannumeric()) end)
+local m_cosh = m.cosh registerscript("m_cosh", function() return m_cosh (scannumeric()) end)
+local m_deg = m.deg registerscript("m_deg", function() return m_deg (scannumeric()) end)
+local m_erf = m.erf registerscript("m_erf", function() return m_erf (scannumeric()) end)
+local m_erfc = m.erfc registerscript("m_erfc", function() return m_erfc (scannumeric()) end)
+local m_exp = m.exp registerscript("m_exp", function() return m_exp (scannumeric()) end)
+local m_exp2 = m.exp2 registerscript("m_exp2", function() return m_exp2 (scannumeric()) end)
+local m_expm1 = m.expm1 registerscript("m_expm1", function() return m_expm1 (scannumeric()) end)
+local m_fabs = m.fabs registerscript("m_fabs", function() return m_fabs (scannumeric()) end)
+local m_fdim = m.fdim registerscript("m_fdim", function() return m_fdim (scanpair ()) end)
+local m_floor = m.floor registerscript("m_floor", function() return m_floor (scannumeric()) end)
+local m_fma = m.fma registerscript("m_fma", function() return m_fma (scancolor ()) end)
+local m_fmax = m.fmax registerscript("m_fmax", function() return m_fmax (scannumeric()) end)
+local m_fmin = m.fmin registerscript("m_fmin", function() return m_fmin (scannumeric()) end)
+local m_fmod = m.fmod registerscript("m_fmod", function() return m_fmod (scanpair ()) end)
+local m_frexp = m.frexp registerscript("m_frexp", function() return m_frexp (scannumeric()) end)
+local m_gamma = m.gamma registerscript("m_gamma", function() return m_gamma (scannumeric()) end)
+local m_hypot = m.hypot registerscript("m_hypot", function() return m_hypot (scanpair ()) end)
+local m_isfinite = m.isfinite registerscript("m_isfinite", function() return m_isfinite (scannumeric()) end)
+local m_isinf = m.isinf registerscript("m_isinf", function() return m_isinf (scannumeric()) end)
+local m_isnan = m.isnan registerscript("m_isnan", function() return m_isnan (scannumeric()) end)
+local m_isnormal = m.isnormal registerscript("m_isnormal", function() return m_isnormal (scannumeric()) end)
+local m_j0 = m.j0 registerscript("m_j0", function() return m_j0 (scannumeric()) end)
+local m_j1 = m.j1 registerscript("m_j1", function() return m_j1 (scannumeric()) end)
+local m_jn = m.jn registerscript("m_jn", function() return m_jn (scanpair ()) end)
+local m_ldexp = m.ldexp registerscript("m_ldexp", function() return m_ldexp (scanpair ()) end)
+local m_lgamma = m.lgamma registerscript("m_lgamma", function() return m_lgamma (scannumeric()) end)
+local m_log = m.log registerscript("m_log", function() return m_log (scannumeric()) end)
+local m_log10 = m.log10 registerscript("m_log10", function() return m_log10 (scannumeric()) end)
+local m_log1p = m.log1p registerscript("m_log1p", function() return m_log1p (scannumeric()) end)
+local m_log2 = m.log2 registerscript("m_log2", function() return m_log2 (scannumeric()) end)
+local m_logb = m.logb registerscript("m_logb", function() return m_logb (scannumeric()) end)
+local m_modf = m.modf registerscript("m_modf", function() return m_modf (scannumeric()) end)
+local m_nearbyint = m.nearbyint registerscript("m_nearbyint", function() return m_nearbyint(scannumeric()) end)
+local m_nextafter = m.nextafter registerscript("m_nextafter", function() return m_nextafter(scanpair ()) end)
+local m_pow = m.pow registerscript("m_pow", function() return m_pow (scanpair ()) end)
+local m_rad = m.rad registerscript("m_rad", function() return m_rad (scannumeric()) end)
+local m_remainder = m.remainder registerscript("m_remainder", function() return m_remainder(scanpair ()) end)
+local m_remquo = m.remquo registerscript("m_remquo", function() return m_remquo (scannumeric()) end)
+local m_round = m.round registerscript("m_round", function() return m_round (scannumeric()) end)
+local m_scalbn = m.scalbn registerscript("m_scalbn", function() return m_scalbn (scanpair ()) end)
+local m_sin = m.sin registerscript("m_sin", function() return m_sin (scannumeric()) end)
+local m_sinh = m.sinh registerscript("m_sinh", function() return m_sinh (scannumeric()) end)
+local m_sqrt = m.sqrt registerscript("m_sqrt", function() return m_sqrt (scannumeric()) end)
+local m_tan = m.tan registerscript("m_tan", function() return m_tan (scannumeric()) end)
+local m_tanh = m.tanh registerscript("m_tanh", function() return m_tanh (scannumeric()) end)
+local m_tgamma = m.tgamma registerscript("m_tgamma", function() return m_tgamma (scannumeric()) end)
+local m_trunc = m.trunc registerscript("m_trunc", function() return m_trunc (scannumeric()) end)
+local m_y0 = m.y0 registerscript("m_y0", function() return m_y0 (scannumeric()) end)
+local m_y1 = m.y1 registerscript("m_y1", function() return m_y1 (scannumeric()) end)
+local m_yn = m.yn registerscript("m_yn", function() return m_yn (scanpair ()) end)
+
+local c_topair = c.topair
+local c_new = c.new
+
+local c_sin = c.sin registerscript("c_sin", function() return mppair(c_topair(c_sin (c_new(scanpair())))) end)
+local c_cos = c.cos registerscript("c_cos", function() return mppair(c_topair(c_cos (c_new(scanpair())))) end)
+local c_tan = c.tan registerscript("c_tan", function() return mppair(c_topair(c_tan (c_new(scanpair())))) end)
+local c_sinh = c.sinh registerscript("c_sinh", function() return mppair(c_topair(c_sinh (c_new(scanpair())))) end)
+local c_cosh = c.cosh registerscript("c_cosh", function() return mppair(c_topair(c_cosh (c_new(scanpair())))) end)
+local c_tanh = c.tanh registerscript("c_tanh", function() return mppair(c_topair(c_tanh (c_new(scanpair())))) end)
+
+local c_asin = c.asin registerscript("c_asin", function() return mppair(c_topair(c_sin (c_new(scanpair())))) end)
+local c_acos = c.acos registerscript("c_acos", function() return mppair(c_topair(c_cos (c_new(scanpair())))) end)
+local c_atan = c.atan registerscript("c_atan", function() return mppair(c_topair(c_tan (c_new(scanpair())))) end)
+local c_asinh = c.asinh registerscript("c_asinh", function() return mppair(c_topair(c_sinh (c_new(scanpair())))) end)
+local c_acosh = c.acosh registerscript("c_acosh", function() return mppair(c_topair(c_cosh (c_new(scanpair())))) end)
+local c_atanh = c.atanh registerscript("c_atanh", function() return mppair(c_topair(c_tanh (c_new(scanpair())))) end)
+
+local c_sqrt = c.sqrt registerscript("c_sqrt", function() return mppair(c_topair(c_sqrt (c_new(scanpair())))) end)
+local c_abs = c.abs registerscript("c_abs", function() return c_topair(c_abs (c_new(scanpair()))) end)
+local c_arg = c.arg registerscript("c_arg", function() return c_topair(c_arg (c_new(scanpair()))) end)
+local c_conj = c.conj registerscript("c_conj", function() return mppair(c_topair(c_conj (c_new(scanpair())))) end)
+local c_exp = c.exp registerscript("c_exp", function() return mppair(c_topair(c_exp (c_new(scanpair())))) end)
+local c_log = c.log registerscript("c_log", function() return mppair(c_topair(c_log (c_new(scanpair())))) end)
+local c_proj = c.proj registerscript("c_proj", function() return mppair(c_topair(c_proj (c_new(scanpair())))) end)
+
+local c_erf = c.erf registerscript("c_erf", function() return mppair(c_topair(c_erf (c_new(scanpair())))) end)
+local c_erfc = c.erfc registerscript("c_erfc", function() return mppair(c_topair(c_erfc (c_new(scanpair())))) end)
+local c_erfcx = c.erfcx registerscript("c_erfcx", function() return mppair(c_topair(c_erfcx (c_new(scanpair())))) end)
+local c_erfi = c.erfi registerscript("c_erfi", function() return mppair(c_topair(c_erfi (c_new(scanpair())))) end)
+local c_dawson = c.dawson registerscript("c_dawson", function() return mppair(c_topair(c_dawson(c_new(scanpair())))) end)
+
+local c_voigt = c.voigt
+local c_voigt_hwhm = c.voigt_hwhm
+
+registerscript("c_voigt", function()
+ return mppair(c_topair(c_voigt(c_new(scanpair()),c_new(scanpair()),c_new(scanpair()))))
+end)
+
+registerscript("c_voigt_hwhm", function()
+ return mppair(c_topair(c_voigt_hwhm(c_new(scanpair()),c_new(scanpair()))))
+end)
+
+local c_pow = c.pow registerscript("c_pow", function() return mppair(c_topair(c_pow(c_new(scanpair()),c_new(scanpair())))) end)
+local c_add = c.add registerscript("c_add", function() return mppair(c_topair(c_add(c_new(scanpair()),c_new(scanpair())))) end)
+local c_sub = c.sub registerscript("c_sub", function() return mppair(c_topair(c_sub(c_new(scanpair()),c_new(scanpair())))) end)
+local c_mul = c.mul registerscript("c_mul", function() return mppair(c_topair(c_mul(c_new(scanpair()),c_new(scanpair())))) end)
+local c_div = c.div registerscript("c_div", function() return mppair(c_topair(c_div(c_new(scanpair()),c_new(scanpair())))) end)
+
+local c_imag = c.imag registerscript("c_imag", function() return c_topair(c_imag(c_new(scanpair()))) end)
+local c_real = c.real registerscript("c_real", function() return c_topair(c_real(c_new(scanpair()))) end)
+local c_neg = c.neg registerscript("c_new", function() return c_topair(c_neg (c_new(scanpair()))) end)
diff --git a/tex/context/base/mkiv/mlib-run.lua b/tex/context/base/mkiv/mlib-run.lua
index 0118f6cbd..fb1367151 100644
--- a/tex/context/base/mkiv/mlib-run.lua
+++ b/tex/context/base/mkiv/mlib-run.lua
@@ -434,8 +434,11 @@ function metapost.checkformat(mpsinput,method)
if file.suffix(mpsinput) ~= "" then
foundfile = find_file(mpsinput) or ""
end
- if foundfile == "" then
- foundfile = find_file(file.replacesuffix(mpsinput,"mpvi")) or ""
+ -- if foundfile == "" then
+ -- foundfile = find_file(file.replacesuffix(mpsinput,"mpvi")) or ""
+ -- end
+ if CONTEXTLMTXMODE > 0 and foundfile == "" then
+ foundfile = find_file(file.replacesuffix(mpsinput,"mpxl")) or ""
end
if foundfile == "" then
foundfile = find_file(file.replacesuffix(mpsinput,"mpiv")) or ""
diff --git a/tex/context/base/mkiv/mlib-scn.lua b/tex/context/base/mkiv/mlib-scn.lua
new file mode 100644
index 000000000..4045173ac
--- /dev/null
+++ b/tex/context/base/mkiv/mlib-scn.lua
@@ -0,0 +1,529 @@
+if not modules then modules = { } end modules ['mlib-scn'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- Very experimental, for Alan and me.
+
+-- for i = 1 upto 32000 : % 0.062
+-- ts := 5mm / 20;
+-- endfor ;
+--
+-- for i = 1 upto 32000 : % 0.219
+-- ts := (getparameter "axis" "sy") / 20;
+-- endfor ;
+--
+-- for i = 1 upto 32000 : % 0.266
+-- ts := (getparameterx "axis" "sy") / 20;
+-- endfor ;
+--
+-- pushparameters "axis";
+-- for i = 1 upto 32000 : % 0.250
+-- ts := (getparameterx "sy") / 20;
+-- endfor ;
+-- popparameters;
+
+local type, next = type, next
+local byte = string.byte
+local insert, remove = table.insert, table.remove
+
+local codes = mplib.codes()
+local types = mplib.types()
+
+table.hashed(codes)
+table.hashed(types)
+
+metapost.codes = codes
+metapost.types = types
+
+local setmetatableindex = table.setmetatableindex
+
+local scanners = mp.scan
+
+local scannext = scanners.next
+local scanexpression = scanners.expression
+local scantoken = scanners.token
+local scansymbol = scanners.symbol
+local scannumeric = scanners.numeric
+local scannumber = scanners.number
+local scaninteger = scanners.integer
+local scanboolean = scanners.boolean
+local scanstring = scanners.string
+local scanpair = scanners.pair
+local scancolor = scanners.color
+local scancmykcolor = scanners.cmykcolor
+local scantransform = scanners.transform
+local scanpath = scanners.path
+
+local mpprint = mp.print
+local mpnumeric = mp.numeric
+local mpstring = mp.string
+local mpquoted = mp.quoted
+local mpboolean = mp.boolean
+local mppair = mp.pair
+local mppath = mp.path
+local mptriplet = mp.triplet
+local mpquadruple = mp.quadruple
+local mpvalue = mp.value
+
+local report = logs.reporter("metapost")
+
+local <const> semicolon_code = codes.semicolon
+local <const> equals_code = codes.equals
+local <const> comma_code = codes.comma
+local <const> colon_code = codes.colon
+local <const> leftbrace_code = codes.leftbrace
+local <const> rightbrace_code = codes.rightbrace
+local <const> leftbracket_code = codes.leftbracket
+local <const> rightbracket_code = codes.rightbracket
+local <const> leftdelimiter_code = codes.leftdelimiter
+local <const> rightdelimiter_code = codes.rightdelimiter
+local <const> numeric_code = codes.numeric
+local <const> string_code = codes.string
+local <const> capsule_code = codes.capsule
+local <const> nullary_code = codes.nullary
+local <const> tag_code = codes.tag
+
+local typescanners = nil
+local tokenscanners = nil
+local scanset = nil
+local scanparameters = nil
+
+scanset = function() -- can be optimized, we now read twice
+ scantoken()
+ if scantoken(true) == rightbrace_code then
+ scantoken()
+ return { }
+ else
+ local l = { }
+ local i = 0
+ while true do
+ i = i + 1
+ local s = scansymbol(true)
+ if s == "{" then
+ l[i] = scanset()
+ elseif s == "[" then
+ local d = { }
+ scansymbol()
+ while true do
+ local s = scansymbol()
+ if s == "]" then
+ break;
+ elseif s == "," then
+ -- continue
+ else
+ local t = scantoken(true)
+ if t == equals_code or t == colon_code then
+ scantoken()
+ end
+ d[s] = tokenscanners[scantoken(true)]()
+ end
+ end
+ l[i] = d
+ else
+ local e = scanexpression(true)
+ l[i] = (typescanners[e] or scanexpression)()
+ end
+ if scantoken() == rightbrace_code then
+ break
+ else
+ -- whatever
+ end
+ end
+ return l
+ end
+end
+
+tokenscanners = {
+ [leftbrace_code] = scanset,
+ [numeric_code] = scannumeric,
+ [string_code] = scanstring,
+ [nullary_code] = scanboolean, -- todo
+}
+
+typescanners = {
+ [types.known] = scannumeric,
+ [types.numeric] = scannumeric,
+ [types.string] = scanstring,
+ [types.boolean] = scanboolean,
+ [types.pair] = function() return scanpair (true) end,
+ [types.color] = function() return scancolor (true) end,
+ [types.cmykcolor] = function() return scancmykcolor(true) end,
+ [types.transform] = function() return scantransform(true) end,
+ [types.path] = function() return scanpath () end,
+}
+
+table.setmetatableindex(tokenscanners,function()
+ local e = scanexpression(true)
+ return typescanners[e] or scanexpression
+end)
+
+local function scanparameters(fenced)
+ local data = { }
+ local close = "]"
+ if not fenced then
+ close = ";"
+ elseif scansymbol(true) == "[" then
+ scansymbol()
+ else
+ return data
+ end
+ while true do
+ local s = scansymbol()
+ if s == close then
+ break;
+ elseif s == "," then
+ -- continue
+ else
+ local t = scantoken(true)
+ if t == equals_code or t == colon_code then
+ -- optional equal or :
+ scantoken()
+ end
+ data[s] = tokenscanners[scantoken(true)]()
+ end
+ end
+ return data
+end
+
+local namespaces = { }
+local presets = { }
+local passed = { }
+
+local function get_parameters(nested)
+ local data = { }
+ if nested or scansymbol(true) == "[" then
+ scansymbol()
+ else
+ return data
+ end
+ while true do
+ -- a key like 'color' has code 'declare'
+ -- print(scansymbol(true),scantoken(true),codes[scantoken(true)])
+ local s = scansymbol()
+ if s == "]" then
+ break;
+ elseif s == "," then
+ -- continue
+ else
+ local t = scantoken(true)
+ if t == equals_code or t == colon_code then
+ -- optional equal or :
+ scantoken()
+ end
+ local kind = scantoken(true)
+ if kind == leftdelimiter_code or kind == tag_code then
+ kind = scanexpression(true)
+ data[s] = (typescanners[kind] or scanexpression)()
+ elseif kind == leftbracket_code then
+ data[s] = get_parameters(true)
+ else
+ data[s] = tokenscanners[kind]()
+ end
+ end
+ end
+ return data
+end
+
+local function getparameters()
+ local namespace = scanstring()
+ -- same as below
+ local parameters = get_parameters()
+ local presets = presets[namespace]
+ local passed = passed[namespace]
+ if passed then
+ if presets then
+ setmetatableindex(passed,presets)
+ end
+ setmetatableindex(parameters,passed)
+ elseif presets then
+ setmetatableindex(parameters,presets)
+ end
+ namespaces[namespace] = parameters
+ --
+end
+
+local function applyparameters()
+ local saved = namespaces
+ local namespace = scanstring()
+ local action = scanstring() -- before we scan the parameters
+ -- same as above
+ local parameters = get_parameters()
+ local presets = presets[namespace]
+ local passed = passed[namespace]
+ if passed then
+ if presets then
+ setmetatableindex(passed,presets)
+ end
+ setmetatableindex(parameters,passed)
+ elseif presets then
+ setmetatableindex(parameters,presets)
+ end
+ namespaces[namespace] = parameters
+ -- till here
+ mpprint(action)
+ namespaces = saved
+end
+
+local function presetparameters()
+ local namespace = scanstring()
+ presets[namespace] = get_parameters()
+end
+
+local function collectnames()
+ local l = { } -- can be reused but then we can't nest
+ local n = 0
+ while true do
+ local t = scantoken(true)
+ -- (1) not really needed
+ if t == numeric_code or t == capsule_code then
+ n = n + 1 l[n] = scaninteger(1)
+ elseif t == string_code then
+ n = n + 1 l[n] = scanstring(1)
+ elseif t == nullary_code then
+ n = n + 1 l[n] = scanboolean(1)
+ elseif t == leftdelimiter_code then
+ t = scanexpression(true)
+ n = n + 1 l[n] = (typescanners[t] or scanexpression)()
+ else
+ break
+ end
+ end
+ return l, n
+end
+
+local function get(v)
+ local t = type(v)
+ if t == "number" then
+ return mpnumeric(v)
+ elseif t == "boolean" then
+ return mpboolean(v)
+ elseif t == "string" then
+ return mpquoted(v)
+ elseif t == "table" then
+ local n = #v
+ if type(v[1]) == "table" then
+ return mppath(v) -- cycle ?
+ elseif n == 2 then
+ return mppair(v)
+ elseif n == 3 then
+ return mptriplet(v)
+ elseif n == 4 then
+ return mpquadruple(v)
+ end
+ end
+ return mpnumeric(0)
+end
+
+local stack = { }
+
+local function pushparameters()
+ local l, n = collectnames()
+ insert(stack,namespaces)
+ for i=1,n do
+ local n = namespaces[l[i]]
+ if type(n) == "table" then
+ namespaces = n
+ else
+ break
+ end
+ end
+end
+
+local function popparameters()
+ local n = remove(stack)
+ if n then
+ namespaces = n
+ else
+ report("stack error")
+ end
+end
+
+local function getparameter()
+ local list, n = collectnames()
+ local v = namespaces
+ for i=1,n do
+ local l = list[i]
+ local vl = v[l]
+ if vl == nil then
+ if type(l) == "number" then
+ vl = v[1]
+ if vl == nil then
+ return mpnumeric(0)
+ end
+ else
+ return mpnumeric(0)
+ end
+ end
+ v = vl
+ end
+ if v == nil then
+ return mpnumeric(0)
+ else
+ return get(v)
+ end
+end
+
+local function getparameterdefault()
+ local list, n = collectnames()
+ local v = namespaces
+ for i=1,n-1 do
+ local l = list[i]
+ local vl = v[l]
+ if vl == nil then
+ if type(l) == "number" then
+ vl = v[1]
+ if vl == nil then
+ return get(list[n])
+ end
+ else
+ return get(list[n])
+ end
+ end
+ v = vl
+ end
+ if v == nil then
+ return get(list[n])
+ else
+ return get(v)
+ end
+end
+
+local function getparametercount()
+ local list, n = collectnames()
+ local v = namespaces
+ for i=1,n do
+ v = v[list[i]]
+ if not v then
+ break
+ end
+ end
+ return mpnumeric(type(v) == "table" and #v or 0)
+end
+
+local validconnectors = {
+ [".."] = true,
+ ["..."] = true,
+ ["--"] = true,
+}
+
+local function getparameterpath()
+ local list, n = collectnames()
+ local close = list[n]
+ if type(close) == "boolean" then
+ n = n - 1
+ else
+ close = false
+ end
+ local connector = list[n]
+ if type(connector) == "string" and validconnectors[connector] then
+ n = n - 1
+ else
+ connector = "--"
+ end
+ local v = namespaces
+ for i=1,n do
+ v = v[list[i]]
+ if not v then
+ break
+ end
+ end
+ if type(v) == "table" then
+ return mppath(v,connector,close)
+ else
+ return mppair(0,0)
+ end
+end
+
+local function getparametertext()
+ local list, n = collectnames()
+ local strut = list[n]
+ if type(strut) == "boolean" then
+ n = n - 1
+ else
+ strut = false
+ end
+ local v = namespaces
+ for i=1,n do
+ v = v[list[i]]
+ if not v then
+ break
+ end
+ end
+ if type(v) == "string" then
+ return mpquoted("\\strut " .. v)
+ else
+ return mpquoted("")
+ end
+end
+
+metapost.registerscript("getparameters", getparameters)
+metapost.registerscript("applyparameters", applyparameters)
+metapost.registerscript("presetparameters", presetparameters)
+metapost.registerscript("getparameter", getparameter)
+metapost.registerscript("getparameterdefault", getparameterdefault)
+metapost.registerscript("getparametercount", getparametercount)
+metapost.registerscript("getparameterpath", getparameterpath)
+metapost.registerscript("getparametertext", getparametertext)
+metapost.registerscript("pushparameters", pushparameters)
+metapost.registerscript("popparameters", popparameters)
+
+-- tex scanners
+
+local scanners = tokens.scanners
+local scanhash = scanners.hash
+local scanstring = scanners.string
+local scanvalue = scanners.value
+local scaninteger = scanners.integer
+local scanboolean = scanners.boolean
+local scanfloat = scanners.float
+local scandimension = scanners.dimension
+
+local definitions = { }
+
+local <const> bpfactor = number.dimenfactors.bp
+local <const> comma = byte(",")
+local <const> close = byte("]")
+
+local scanrest = function() return scanvalue(comma,close) or "" end
+local scandimension = function() return scandimension() * bpfactor end
+
+local scanners = {
+ ["integer"] = scaninteger,
+ ["number"] = scanfloat,
+ ["numeric"] = scanfloat,
+ ["boolean"] = scanboolean,
+ ["string"] = scanrest,
+ ["dimension"] = scandimension,
+}
+
+interfaces.implement {
+ name = "lmt_parameters_define",
+ arguments = "string",
+ actions = function(namespace)
+ local d = scanhash()
+ for k, v in next, d do
+ d[k] = scanners[v] or scanrest
+ end
+ definitions[namespace] = d
+ end,
+}
+
+interfaces.implement {
+ name = "lmt_parameters_preset",
+ arguments = "string",
+ actions = function(namespace)
+ passed[namespace] = scanhash(definitions[namespace])
+ end,
+}
+
+interfaces.implement {
+ name = "lmt_parameters_reset",
+ arguments = "string",
+ actions = function(namespace)
+ passed[namespace] = nil
+ end,
+}
diff --git a/tex/context/base/mkiv/mult-aux.mkiv b/tex/context/base/mkiv/mult-aux.mkiv
index d77ec82a1..b29478a56 100644
--- a/tex/context/base/mkiv/mult-aux.mkiv
+++ b/tex/context/base/mkiv/mult-aux.mkiv
@@ -11,17 +11,9 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% todo: setupxxx and setupxxxs (so a plural for the root setup and
-% we can consider blocking the root)
-
-% todo (e.g for columnsets and registers): \definexxx[parent][1]
-%
-
-%D A generalization of \MKIV-like inheritance. Just something to play
-%D with (interface might change). The code here evolved in an email
-%D exchange between me and Wolgang Schuster.
-
-% todo: doifelse<whatever>
+%D A generalization of \MKIV-like inheritance. Just something to play with
+%D (interface might change). The code here evolved in an email exchange between me
+%D and Wolgang Schuster.
\writestatus{loading}{ConTeXt Multilingual Macros / Helpers}
@@ -76,15 +68,15 @@
% todo: add (relaxed) postsetup and postdefine hooks, just after the everys
-% Start of experimental code: especially tables can have many assignments
-% and although most time is spent in the typesetting anyway, we can squeeze
-% out a little bit. Of course having 500 rows of 50 columns each with some
-% setting does not happen that often. One should keep in mind that in the
-% average document having some 500 assignments is no exception but there we're
-% talking of neglectable runtime for them. Of course in the definitions below
-% there is no real gain, only in the generated \setup* commands. Another
-% situation with many assignments is \XML\ where we can pass attributes
-% and normally don't do testing of them making sense.
+%D Start of experimental code: especially tables can have many assignments and
+%D although most time is spent in the typesetting anyway, we can squeeze out a
+%D little bit. Of course having 500 rows of 50 columns each with some setting does
+%D not happen that often. One should keep in mind that in the average document
+%D having some 500 assignments is no exception but there we're talking of
+%D neglectable runtime for them. Of course in the definitions below there is no real
+%D gain, only in the generated \setup* commands. Another situation with many
+%D assignments is \XML\ where we can pass attributes and normally don't do testing
+%D of them making sense.
%
% \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s
% \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s
@@ -216,9 +208,9 @@
% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par
%
% slower: \def#3##1{\csname\ifcsname#1#2:##1\endcsname\expandafter\csstring\lastnamedcs\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
-%
-% pre-expansion can be a bit faster but handly any effect on a normal run so let's go for
-% saving some memory
+
+%D pre-expansion can be a bit faster but handly any effect on a normal run so let's
+%D go for saving some memory
\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}
@@ -281,8 +273,7 @@
\expandafter\noexpand\csname check#2parent\endcsname
\expandafter\noexpand\csname chaintocurrent#2\endcsname}}
-% In \MKIV\ we can probably use the english variant for all other
-% languages too.
+%D In \MKIV\ we can probably use the english variant for all other languages too.
% todo: inline the def/let
@@ -685,14 +676,14 @@
\installsetuphandler {#1}{#2}%
\installstyleandcolorhandler {#1}{#2}}
-%D Many mechanisms have some kind of inheritance in place, and these are
-%D the speed||critical ones. Therefore there is no reason to stick to
-%D \type {\@@xxkey} for the sake of performance. For this reason we also
-%D provide a direct variant. This permits a more consistent treatment of
-%D namespaces. A \type {\whateverparameter} call is three times slower
-%D and a \type {\directwhateverparameter} call two times but for some
-%D 100K expansions we only loose some .1 second which is neglectable
-%D given the small amount of expansions in real runs.
+%D Many mechanisms have some kind of inheritance in place, and these are the
+%D speed||critical ones. Therefore there is no reason to stick to \type {\@@xxkey}
+%D for the sake of performance. For this reason we also provide a direct variant.
+%D This permits a more consistent treatment of namespaces. A \type
+%D {\whateverparameter} call is three times slower and a \type
+%D {\directwhateverparameter} call two times but for some 100K expansions we only
+%D loose some .1 second which is neglectable given the small amount of expansions in
+%D real runs.
%D We don't need colons for such simple cases.
@@ -848,22 +839,21 @@
% \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}}
% \stoptyping
%
-% The following variant is nicer and in principle faster but that gets
-% unnoticed unless lots of expansion happens. Also, we can use long tags
-% but the internal expansion will be relatively small (and unlikely more
-% than 4 characters). For instance, \??xx used to expand to @@xx but now
-% becomes for instance 123::. This is one character more but in quite some
-% cases we had : after such a tag in the old situation. In the new situation
-% we create more namespaces and don't need that : any more, so we end up
-% with on the average the same amount of tokens and definitely less when
-% we consider cases like \??xx:\c!align: which now is just \??somealign and
-% therefore has length 5 now (instead of 4+1+5+1=10).
+% The following variant is nicer and in principle faster but that gets unnoticed
+% unless lots of expansion happens. Also, we can use long tags but the internal
+% expansion will be relatively small (and unlikely more than 4 characters). For
+% instance, \??xx used to expand to @@xx but now becomes for instance 123::. This
+% is one character more but in quite some cases we had : after such a tag in the
+% old situation. In the new situation we create more namespaces and don't need that
+% : any more, so we end up with on the average the same amount of tokens and
+% definitely less when we consider cases like \??xx:\c!align: which now is just
+% \??somealign and therefore has length 5 now (instead of 4+1+5+1=10).
%
-% Eventualy we will have a verbose \blablanamespace and the difference between
-% core and regular can go ... after all, \xxxparameter can already clash between
-% the two prefix groups .. if users use this mechanism a lot they should use
-% verbose names anyway (the old two character names were mostly an optimization
-% as they also expanded to these characters).
+% Eventualy we will have a verbose \blablanamespace and the difference between core
+% and regular can go ... after all, \xxxparameter can already clash between the two
+% prefix groups .. if users use this mechanism a lot they should use verbose names
+% anyway (the old two character names were mostly an optimization as they also
+% expanded to these characters).
% todo: register namespaces at lua end for logging and reverse resolve
% todo: move this to syst-ini so that we can use it real early
@@ -936,8 +926,8 @@
\usedummystyleparameter
\usedummycolorparameter
-% Maybe a \definecorenamespace[name][directparameter,directsetup][parent]
-% but we don't gain much. Actually we might just inline all definitions.
+% Maybe a \definecorenamespace[name][directparameter,directsetup][parent] but we
+% don't gain much. Actually we might just inline all definitions.
% \enabletrackers[interfaces.namespaces,context.flush]
%
@@ -1429,74 +1419,45 @@
\installcorenamespace{commalistprocessornext}
\installcorenamespace{commalistprocessoraction}
-\startmkivmode
-
- \installcorenamespace{commalistprocessorcheck}
- \installcorenamespace{commalistprocessorspace}
- \installcorenamespace{commalistprocessorpickup}
- \installcorenamespace{commalistprocessorfinish}
-
- \unexpanded\def\installcommalistprocessor#1#2% 8 macro names overhead
- {\let\nexttoken\relax
- \unexpanded\expandafter\edef\csname\??commalistprocessor#1\endcsname[%
- {\futurelet\nexttoken\csname\??commalistprocessorcheck#1\endcsname}%
- \unexpanded\expandafter\edef\csname\??commalistprocessorcheck#1\endcsname
- {\noexpand\ifx\nexttoken]%
- \noexpand\expandafter\noexpand\gobblethreearguments
- \noexpand\else
- \noexpand\expandafter\csname\??commalistprocessorwrap#1\endcsname
- \noexpand\fi
- \relax}% this one preserved the next {}
- \unexpanded\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]%
- {\csname\??commalistprocessorfirst#1\endcsname##1,]\relax}%
- \unexpanded\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname##1% picks up \relax
- {\csname\??commalistprocessornext#1\endcsname}%
- \unexpanded\expandafter\edef\csname\??commalistprocessornext#1\endcsname
- {\noexpand\ifx\nexttoken\noexpand\blankspace
- \noexpand\expandafter\csname\??commalistprocessorspace#1\endcsname
- \noexpand\else
- \noexpand\expandafter\csname\??commalistprocessorfinish#1\endcsname
- \noexpand\fi}%
- \unexpanded\expandafter\edef\csname\??commalistprocessorfinish#1\endcsname
- {\noexpand\ifx\nexttoken]%
- \noexpand\expandafter\noexpand\gobbleoneargument
- \noexpand\else
- \noexpand\expandafter\csname\??commalistprocessoraction#1\endcsname
- \noexpand\fi}%
- \unexpanded\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,%
- {\noexpand#2{##1}%
- \futurelet\nexttoken\csname\??commalistprocessornext#1\endcsname}%
- \let\next\:%
- \unexpanded\edef \:{\csname\??commalistprocessorspace#1\endcsname}%
- \unexpanded\expandafter\edef\: {\futurelet\nexttoken\csname\??commalistprocessornext#1\endcsname}%
- \let\:\next}
-
-\stopmkivmode
-
-\startlmtxmode
-
- %installcorenamespace{commalistprocessorpickup}
-
- \unexpanded\def\installcommalistprocessor#1#2% 5 macro names overhead
- {\unexpanded\expandafter\edef\csname\??commalistprocessor#1\endcsname[%
- % {\noexpand\futureexpandis]%
- % \noexpand\gobbleoneargument
- % \csname\??commalistprocessorpickup#1\endcsname}
- %\unexpanded\expandafter\edef\csname\??commalistprocessorpickup#1\endcsname
- {\csname\??commalistprocessorwrap#1\endcsname\relax}% \relax preserves {}
- \unexpanded\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]%
- {\csname\??commalistprocessorfirst#1\endcsname##1,]}
- \unexpanded\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname\relax
- {\csname\??commalistprocessornext#1\endcsname}%
- \unexpanded\expandafter\edef\csname\??commalistprocessornext#1\endcsname
- {\noexpand\futureexpandis]%
- \noexpand\gobbleoneargument
- \csname\??commalistprocessoraction#1\endcsname}
- \unexpanded\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,%
- {\noexpand#2{##1}%
- \csname\??commalistprocessornext#1\endcsname}}
-
-\stoplmtxmode
+\installcorenamespace{commalistprocessorcheck}
+\installcorenamespace{commalistprocessorspace}
+\installcorenamespace{commalistprocessorpickup}
+\installcorenamespace{commalistprocessorfinish}
+
+\unexpanded\def\installcommalistprocessor#1#2% 8 macro names overhead
+ {\let\nexttoken\relax
+ \unexpanded\expandafter\edef\csname\??commalistprocessor#1\endcsname[%
+ {\futurelet\nexttoken\csname\??commalistprocessorcheck#1\endcsname}%
+ \unexpanded\expandafter\edef\csname\??commalistprocessorcheck#1\endcsname
+ {\noexpand\ifx\nexttoken]%
+ \noexpand\expandafter\noexpand\gobblethreearguments
+ \noexpand\else
+ \noexpand\expandafter\csname\??commalistprocessorwrap#1\endcsname
+ \noexpand\fi
+ \relax}% this one preserved the next {}
+ \unexpanded\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]%
+ {\csname\??commalistprocessorfirst#1\endcsname##1,]\relax}%
+ \unexpanded\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname##1% picks up \relax
+ {\csname\??commalistprocessornext#1\endcsname}%
+ \unexpanded\expandafter\edef\csname\??commalistprocessornext#1\endcsname
+ {\noexpand\ifx\nexttoken\noexpand\blankspace
+ \noexpand\expandafter\csname\??commalistprocessorspace#1\endcsname
+ \noexpand\else
+ \noexpand\expandafter\csname\??commalistprocessorfinish#1\endcsname
+ \noexpand\fi}%
+ \unexpanded\expandafter\edef\csname\??commalistprocessorfinish#1\endcsname
+ {\noexpand\ifx\nexttoken]%
+ \noexpand\expandafter\noexpand\gobbleoneargument
+ \noexpand\else
+ \noexpand\expandafter\csname\??commalistprocessoraction#1\endcsname
+ \noexpand\fi}%
+ \unexpanded\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,%
+ {\noexpand#2{##1}%
+ \futurelet\nexttoken\csname\??commalistprocessornext#1\endcsname}%
+ \let\next\:%
+ \unexpanded\edef \:{\csname\??commalistprocessorspace#1\endcsname}%
+ \unexpanded\expandafter\edef\: {\futurelet\nexttoken\csname\??commalistprocessornext#1\endcsname}%
+ \let\:\next}
\unexpanded\def\installcommalistprocessorcommand#1#2% \processor \action
{\edef\p_name{\csstring#2}%
diff --git a/tex/context/base/mkiv/mult-aux.mkxl b/tex/context/base/mkiv/mult-aux.mkxl
new file mode 100644
index 000000000..8343fb8dd
--- /dev/null
+++ b/tex/context/base/mkiv/mult-aux.mkxl
@@ -0,0 +1,1154 @@
+%D \module
+%D [ file=mult-aux,
+%D version=2010.08.2,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D A generalization of \MKIV-like inheritance. Just something to play with
+%D (interface might change). The code here evolved in an email exchange between me
+%D and Wolgang Schuster.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Helpers}
+
+\registerctxluafile{mult-aux}{}
+
+\unprotect
+
+\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % hex 19
+
+% \edef\s!parent{\Uchar29} % inlining  is ugly, a tiny bit faster, but neglectable on a run
+
+%D \starttyping
+%D \unprotect
+%D \def\????aa{@@@@aa}
+%D
+%D \installparameterhandler \????aa {whatever}
+%D \installsetuphandler \????aa {whatever}
+%D \installdefinehandler \????aa {whatever} \????aa % #3 == defaultroot
+%D \installfontandcolorhandler\????aa {whatever}
+%D
+%D % \installcommandhandler \????aa {whatever} \????aa
+%D \protect
+%D
+%D % \whateverparameter \c!test
+%D % \whateverparameterhash \c!test
+%D % \namedwhateverparameter \mycurrentwhatever \c!test
+%D % \usewhateverstyleandcolor \c!style \c!color
+%D % \everydefinewhatever (sets \currentwhatever)
+%D % \everypresetwhatever (can be used to reset parameters as we can redefine)
+%D % \everysetupwhatever (sets \currentwhatever)
+%D
+%D \starttext
+%D \definewhatever[first] \definewhatever[second][first]
+%D test: \def\currentwhatever{first} \whateverparameter{method} \par
+%D \setupwhatever [method=unset] test: \def\currentwhatever{first} \whateverparameter{method} \par
+%D \setupwhatever[first] [method=first] test: \def\currentwhatever{first} \whateverparameter{method} \par
+%D test: \def\currentwhatever{second} \whateverparameter{method} \par
+%D \setupwhatever[second][method=second] test: \def\currentwhatever{second} \whateverparameter{method} \par
+%D \stoptext
+%D \stoptyping
+
+% problem: every* could clash
+%
+% There can be less {} in the following definitions if we assume \??aa and \c!somecs
+%
+% todo: \def\detokenized...parameter#1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2\endcsname}} % always root
+%
+% it might be more efficient to do this at the lua and
+%
+% watch the push/pop and predefinition of current .. this is needed for nested
+% definitions and overloaded defines using the predefined one
+
+% todo: add (relaxed) postsetup and postdefine hooks, just after the everys
+
+%D Start of experimental code: especially tables can have many assignments and
+%D although most time is spent in the typesetting anyway, we can squeeze out a
+%D little bit. Of course having 500 rows of 50 columns each with some setting does
+%D not happen that often. One should keep in mind that in the average document
+%D having some 500 assignments is no exception but there we're talking of
+%D neglectable runtime for them. Of course in the definitions below there is no real
+%D gain, only in the generated \setup* commands. Another situation with many
+%D assignments is \XML\ where we can pass attributes and normally don't do testing
+%D of them making sense.
+%
+% \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s
+% \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s
+% \testfeatureonce{100000}{\def\m_mult_interfaces_namespace{bla}\mult_interfaces_get_parameters_indeed[a=111,b=222,c=333]}% 1.466s
+
+\let\m_mult_interfaces_namespace\empty
+
+\def\mult_interfaces_get_parameters#1[#2%
+ {\if\noexpand#2]%
+ \expandafter\gobbleoneargument
+ \else
+ \def\m_mult_interfaces_namespace{#1}%
+ \expandafter\mult_interfaces_get_parameters_indeed
+ \fi#2}
+
+\def\mult_interfaces_get_parameters_indeed#1]% namespace already set
+ {\mult_interfaces_get_parameters_item#1,],^^^^0004}
+
+\def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before ,
+ {\if,#1,% dirty trick for testing #1=empty
+ \expandafter\mult_interfaces_get_parameters_item
+ \orelse\if]#1%
+ \expandafter\gobbleoneargument
+ \else
+ \mult_interfaces_get_parameters_assign#1==\empty^^^^0004%
+ % \expandafter\mult_interfaces_get_parameters_item % saves skipping when at end
+ \fi#2}
+
+\def\mult_interfaces_get_parameters_error#1#2% #3%
+ {\mult_interfaces_get_parameters_error_indeed{#1}{#2}%
+ \gobbleoneargument}
+
+\def\mult_interfaces_get_parameters_error_indeed#1#2%
+ {\showassignerror{#2}{\the\inputlineno\space(#1)}}
+
+\def\mult_interfaces_get_parameters_assign#1=#2=#3#4^^^^0004%
+ {\ifx\empty#1\empty
+ \expandafter\mult_interfaces_get_parameters_error
+ \orelse\ifx#3\empty
+ \expandafter\mult_interfaces_get_parameters_error
+ \else
+ \expandafter\mult_interfaces_def
+ \fi
+ \m_mult_interfaces_namespace{#1}{#2}%
+ \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+\startinterface english
+
+ % some 10% faster
+
+ \let\mult_interfaces_get_parameters_error\undefined
+
+ \def\mult_interfaces_get_parameters_error_one#1\csname#2#3\endcsname#4%
+ {\mult_interfaces_get_parameters_error_indeed{#2}{#3}\iftrue}
+
+ \def\mult_interfaces_get_parameters_error_two#1\csname#2#3\endcsname#4%
+ {\mult_interfaces_get_parameters_error_indeed{#2}{#3}}
+
+ \def\mult_interfaces_get_parameters_assign#1=#2=#3#4^^^^0004%
+ {\ifx\empty#1\empty
+ \mult_interfaces_get_parameters_error_one
+ \orelse\ifx#3\empty
+ \mult_interfaces_get_parameters_error_two
+ \else
+ \expandafter\def\csname\m_mult_interfaces_namespace#1\endcsname{#2}%
+ \fi
+ \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+\stopinterface
+
+\newif\ifassignment
+
+\def\mult_check_for_assignment_indeed#1=#2#3^^^^0004%
+ {\if#2^^^^0003\assignmentfalse\else\assignmenttrue\fi}
+
+\def\mult_check_for_assignment_indeed_begin_#1=#2#3^^^^0004%
+ {\if#2^^^^0003}
+
+\def\mult_check_for_assignment#1%
+ {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=^^^^0003^^^^0003^^^^0004}
+
+% End of experimental code.
+
+\unexpanded\def\mult_interfaces_let #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_lete#1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+\unexpanded\def\mult_interfaces_def #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_let #1#2{\expandafter \let\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_lete#1#2{\expandafter \let\csname#1#2\endcsname\empty}
+ \unexpanded\def\mult_interfaces_def #1#2{\expandafter \def\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1#2\endcsname}
+
+\stopinterface
+
+% the commented detokenized variant that backtracks ... needs testing usage first
+%
+% \let\whatever\relax
+%
+% \definetest[oeps][bagger=\whatever]
+%
+% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par
+% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par
+%
+% slower: \def#3##1{\csname\ifcsname#1#2:##1\endcsname\expandafter\csstring\lastnamedcs\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
+
+%D pre-expansion can be a bit faster but handly any effect on a normal run so let's
+%D go for saving some memory
+
+\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}
+
+\unexpanded\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8% inlining \csname*\endcsname is more efficient (#3 and #6 only)
+ {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
+ \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
+ \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
+ %\def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+ %\def#5##1##2{\ifx##1\relax\??empty\else#4##1{##2}\fi}% is {} needed around ##1 ?
+ \def#5##1##2{\ifx##1\relax^^^^0019\else#4##1{##2}\fi}% is {} needed around ##1 ?
+ \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
+ \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
+ \def#8##1{\begincsname#1#2:##1\endcsname}}
+
+\unexpanded\def\installparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_parameter_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname do#2parameter\endcsname % or : #2_parameter
+ \expandafter\noexpand\csname do#2parentparameter\endcsname % or : #2_parent_parameter
+ \expandafter\noexpand\csname named#2parameter\endcsname
+ \expandafter\noexpand\csname detokenized#2parameter\endcsname
+ \expandafter\noexpand\csname direct#2parameter\endcsname}} % strict#2parameter is gone
+
+\unexpanded\def\mult_interfaces_install_root_parameter_handler#1#2#3%
+ {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
+ \def#3##1{\begincsname#1:##1\endcsname}}
+
+\unexpanded\def\installrootparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_root_parameter_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname
+ \expandafter\noexpand\csname root#2parameter\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9%
+ {\ifx#2\relax\let#2\empty\fi
+ \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
+ \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
+ %\def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}%
+ \def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}%
+ \def#6{#1#2:}%
+ \def#7##1{#1##1:}%
+ \def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}%
+ \unexpanded\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}}
+
+\unexpanded\def\installparameterhashhandler#1#2%
+ {\expandafter\let\csname#2namespace\endcsname#1%
+ \normalexpanded
+ {\mult_interfaces_install_parameter_hash_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname #2parameterhash\endcsname
+ \expandafter\noexpand\csname do#2parameterhash\endcsname % or : #2_parameter_hash
+ \expandafter\noexpand\csname do#2parentparameterhash\endcsname % or : #2_parent_parameter_hash
+ \expandafter\noexpand\csname current#2hash\endcsname
+ \expandafter\noexpand\csname named#2hash\endcsname
+ \expandafter\noexpand\csname check#2parent\endcsname
+ \expandafter\noexpand\csname chaintocurrent#2\endcsname}}
+
+%D In \MKIV\ we can probably use the english variant for all other languages too.
+
+% todo: inline the def/let
+
+\unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
+ {\ifx#2\relax\let#2\empty\fi
+ \unexpanded\def#3{\mult_interfaces_def {#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#4{\mult_interfaces_edef{#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#5{\mult_interfaces_let {#1#2:}}% ##1 ##2
+ \unexpanded\def#6{\mult_interfaces_lete{#1#2:}}}% ##1
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
+ {\ifx#2\relax\let#2\empty\fi
+ \unexpanded\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}% ##1 ##2
+ \unexpanded\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1
+
+\stopinterface
+
+\unexpanded\def\installparametersethandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_parameter_set_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname set#2parameter\endcsname
+ \expandafter\noexpand\csname setexpanded#2parameter\endcsname
+ \expandafter\noexpand\csname let#2parameter\endcsname
+ \expandafter\noexpand\csname reset#2parameter\endcsname}}
+
+\let\dousecurrentstyleparameter\relax
+\let\dousecurrentcolorparameter\relax
+
+\let\currentstyleparameter\empty
+\let\currentcolorparameter\empty
+
+\unexpanded\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
+ {\unexpanded\def#2##1##2% style color
+ {\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline)
+ \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi
+ \edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch)
+ \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}%
+ \unexpanded\def#3##1% style
+ {\edef\currentstyleparameter{#1{##1}}% this name is public
+ \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}%
+ \unexpanded\def#4##1% color
+ {\edef\currentcolorparameter{#1{##1}}% this name is public
+ \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}}
+
+\unexpanded\def\installstyleandcolorhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_style_and_color_handler
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters
+ \expandafter\noexpand\csname use#2styleparameter\endcsname
+ \expandafter\noexpand\csname use#2colorparameter\endcsname}}
+
+\let\definehandlerparent\empty
+
+\def\mult_check_for_parent#1#2#3#4%
+ {\ifcsname#1#4:\s!parent\endcsname \else \ifx#4\empty \else
+ \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
+ \fi \fi}
+
+%def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi}
+%def\getparentchain #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+%def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+
+\def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi}
+\def\getparentchain #1#2{\begincsname#1#2:\s!chain\endcsname}
+\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname}
+
+\unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones
+ {\ifx#4\relax\let#4\empty\fi % see \defineregister
+ \unexpanded\def#2{\dotripleempty#5}%
+ \newtoks#6%
+ \newtoks#7%
+ \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
+ {\let#9#4%
+ \edef#4{##1}%
+ \ifthirdargument
+ \the#6% predefine
+ \edef#8{##2}%
+ \mult_check_for_parent{#1}{#3}#4#8%
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#4:}[##3]%
+ \orelse\ifsecondargument
+ \the#6% predefine
+ \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##2}=^^^^0003^^^^0003^^^^0004%
+ \edef#8{##2}%
+ \mult_check_for_parent{#1}{#3}#4#8%
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
+ \else
+ \let#8\empty
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+ \mult_interfaces_get_parameters{#1#4:}[##2]%
+ \fi
+ \else
+ \the#6% predefine
+ \let#8\empty
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+ \fi
+ \the#7%
+ \let#4#9}}
+
+\unexpanded\def\installdefinehandler#1#2#3%
+ {\normalexpanded
+ {\mult_interfaces_install_define_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname define#2\endcsname
+ {\noexpand#3}% root
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname define_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everypreset#2\endcsname
+ \expandafter\noexpand\csname everydefine#2\endcsname
+ \expandafter\noexpand\csname current#2parent\endcsname
+ \expandafter\noexpand\csname saved_defined_#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8#9%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dodoubleempty#4}%
+ \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
+ \newtoks#5%
+ \newtoks#8%
+ \unexpanded\def#4[##1][##2]% maybe helper
+ {\let#7#3%
+ \ifsecondargument
+ \def#9####1% we will have a simple one as well
+ {\edef#3{####1}%
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#5}%
+ \processcommalist[##1]#9%
+ \else
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#5%
+ \fi
+ \let#3#7%
+ \the#8}}
+
+\unexpanded\def\installsetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_setup_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname everysetup#2root\endcsname
+ \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+
+\let\doingrootsetupnamed\plusone % \setuplayout[name][key=value]
+\let\doingrootsetuproot \plustwo % \setuplayout [key=value]
+\let\doingrootsetnamed \plusthree % \setuplayout[name]
+\let\doingrootsetroot \plusfour % \setuplayout
+
+\unexpanded\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dodoubleempty#4}%
+ \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}}
+
+\unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
+ {\newtoks#5%
+ \newconstant#2%
+ \newtoks#8%
+ \newtoks#9%
+ \ifx#6\relax\let#6\empty\fi
+ \unexpanded\def#4[##1][##2]% maybe helper
+ {\ifsecondargument % no commalist here
+ % \setuplayout[whatever][key=value]
+ \let#7#3%
+ \let#6#3%
+ \edef#3{##1}%
+ #2\doingrootsetupnamed
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#5%
+ \ifx#3#6\the#8\fi % only switchsetups if previous == current
+ \let#3#7%
+ \orelse\iffirstargument
+ % \mult_check_for_assignment{##1}%
+ \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004%
+ % \setuplayout[whatever]
+ \let#6#3% % previous becomes current
+ \edef#3{##1}% this will catch reset so one needs to test for it
+ #2\doingrootsetnamed
+ \the#5% % we can check for previous vs current
+ \the#8% switchsetups
+ \else
+ % \setuplayout[key=value]
+ \let#7#3%
+ \let#6#3%
+ \let#3\empty
+ #2\doingrootsetuproot
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#5%
+ \the#8% switchsetups
+ \let#3#7%
+ \fi
+ \else
+ % \setuplayout
+ \let#6#3% % previous becomes current
+ \let#3\empty % current becomes empty
+ #2\doingrootsetroot
+ \the#5%
+ \the#8% switchsetups
+ \fi
+ #2\zerocount % mode is always zero at the end
+ \the#9}}
+
+\unexpanded\def\installswitchsetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_switch_setup_handler_a
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \mult_interfaces_install_switch_setup_handler_b
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname #2setupmode\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname previous#2\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname everyswitch#2\endcsname
+ \expandafter\noexpand\csname everysetup#2root\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8#9%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dotripleempty#4}%
+ \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}%
+ \newtoks#5%
+ \def#4[##1][##2][##3]%
+ {\let#8#3%
+ \ifthirdargument
+ \def#9####1%
+ {\edef#3{####1}%
+ \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
+ \the#5}%
+ \processcommalist[##1]#9%
+ \orelse\ifsecondargument
+ \def#9####1%
+ {\edef#3{####1}%
+ #7% checks parent and sets if needed
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#5}%
+ \processcommalist[##1]#9%
+ \else
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#5%
+ \fi
+ \let#3#8}}
+
+\unexpanded\def\installautosetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_auto_setup_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \expandafter\noexpand\csname check#2parent\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+
+\unexpanded\def\installbasicparameterhandler#1#2%
+ {\installparameterhandler {#1}{#2}%
+ \installparameterhashhandler{#1}{#2}%
+ \installparametersethandler {#1}{#2}%
+ \installrootparameterhandler{#1}{#2}}
+
+\unexpanded\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installautosetuphandler {#1}{#2}}
+
+\unexpanded\def\installstylisticautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installautosetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installswitchsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installautocommandhandler#1#2#3% automatically defined cloned setups
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installautosetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
+ {\installbasicparameterhandler{#1}{#2}%
+ \installsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+%D Many mechanisms have some kind of inheritance in place, and these are the
+%D speed||critical ones. Therefore there is no reason to stick to \type {\@@xxkey}
+%D for the sake of performance. For this reason we also provide a direct variant.
+%D This permits a more consistent treatment of namespaces. A \type
+%D {\whateverparameter} call is three times slower and a \type
+%D {\directwhateverparameter} call two times but for some 100K expansions we only
+%D loose some .1 second which is neglectable given the small amount of expansions in
+%D real runs.
+
+%D We don't need colons for such simple cases.
+
+\unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
+%%{\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
+ {\def#3##1{\begincsname#1##1\endcsname}%
+ \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
+ % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
+ \def#5##1{\begincsname#1##1\endcsname}}
+
+\unexpanded\def\installdirectparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_parameter_handler
+ {\noexpand#1}%
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname detokenized#2parameter\endcsname
+ \expandafter\noexpand\csname direct#2parameter\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5%
+ {\unexpanded\def#2{\dosingleempty#3}%
+ \newtoks#5%
+ \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}%
+ \def#4{\mult_interfaces_get_parameters#1}}
+
+\unexpanded\def\installdirectsetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_setup_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency)
+ \expandafter\noexpand\csname everysetup#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
+ {\unexpanded\def#2{\mult_interfaces_def #1}%
+ \unexpanded\def#3{\mult_interfaces_edef#1}%
+ \unexpanded\def#4{\mult_interfaces_let #1}%
+ \unexpanded\def#5{\mult_interfaces_let #1\empty}}%
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
+ {\unexpanded\def#2##1{\expandafter \def\csname#1##1\endcsname}%
+ \unexpanded\def#3##1{\expandafter\edef\csname#1##1\endcsname}%
+ \unexpanded\def#4##1{\expandafter \let\csname#1##1\endcsname}%
+ \unexpanded\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}%
+
+\stopinterface
+
+\unexpanded\def\installdirectparametersethandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_parameter_set_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname set#2parameter\endcsname
+ \expandafter\noexpand\csname setexpanded#2parameter\endcsname
+ \expandafter\noexpand\csname let#2parameter\endcsname
+ \expandafter\noexpand\csname reset#2parameter\endcsname}}
+
+\let\installdirectstyleandcolorhandler\installstyleandcolorhandler
+
+\unexpanded\def\installdirectcommandhandler#1#2%
+ {\installdirectparameterhandler {#1}{#2}%
+ \installdirectsetuphandler {#1}{#2}%
+ \installdirectparametersethandler {#1}{#2}%
+ \installdirectstyleandcolorhandler{#1}{#2}}
+
+\unexpanded\def\installsetuponlycommandhandler#1#2%
+ {\installdirectparameterhandler{#1}{#2}%
+ \installdirectsetuphandler {#1}{#2}%
+ }% maybe \installdirectparametersethandler {#1}{#2}%
+
+% Experiment:
+
+% \installcorenamespace {one}
+% \installcorenamespace {two}
+%
+% \installcommandhandler \??one {one} \??one
+% \installcommandhandler \??two {two} \??two
+%
+% \defineone[test] \setupone[test][alpha=first]
+% \definetwo[test] \setuptwo[test][beta=second]
+%
+% \protect
+%
+% \def\currentone{test}
+% \def\currenttwo{test}
+%
+% \relateparameterhandlers {two} {test} {one} {test}
+%
+% yes:\oneparameter{alpha}\par
+% nop:\oneparameter{beta}\par
+% yes:\twoparameter{alpha}\par
+% yes:\twoparameter{beta}\par
+
+\unexpanded\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
+ {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}
+
+\unexpanded\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance}
+ {\expandafter\edef\csname#1#2:\s!parent\endcsname{#3#4}}
+
+%D Here is another experiment:
+
+\unexpanded\def\installactionhandler#1%
+ {\normalexpanded
+ {\mult_interfaces_install_action_handler
+ {#1}%
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname setupcurrent#1\endcsname
+ \expandafter\noexpand\csname #1_action\endcsname}}
+
+% \unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4%
+% {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
+% \unexpanded\def#4[##1][##2]%
+% {\begingroup
+% \ifsecondargument
+% \edef#2{##1}%
+% #3[##2]%
+% \else\iffirstargument
+% \doifelseassignment{##1}
+% {\let#2\empty
+% #3[##1]}%
+% {\edef#2{##1}}%
+% \else
+% \let#2\empty
+% \fi\fi
+% \directsetup{handler:action:#1}%
+% \endgroup}}
+
+\unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4%
+ {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
+ \unexpanded\def#4[##1][##2]%
+ {\begingroup
+ \ifsecondargument
+ \edef#2{##1}%
+ #3[##2]%
+ \orelse\iffirstargument
+ \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004%
+ \edef#2{##1}%
+ \else
+ \let#2\empty
+ #3[##1]%
+ \fi
+ \else
+ \let#2\empty
+ \fi
+ \directsetup{handler:action:#1}%
+ \endgroup}}
+
+% First we had, in tune with the regular system variables:
+%
+% \starttyping
+% \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}}
+% \stoptyping
+%
+% The following variant is nicer and in principle faster but that gets unnoticed
+% unless lots of expansion happens. Also, we can use long tags but the internal
+% expansion will be relatively small (and unlikely more than 4 characters). For
+% instance, \??xx used to expand to @@xx but now becomes for instance 123::. This
+% is one character more but in quite some cases we had : after such a tag in the
+% old situation. In the new situation we create more namespaces and don't need that
+% : any more, so we end up with on the average the same amount of tokens and
+% definitely less when we consider cases like \??xx:\c!align: which now is just
+% \??somealign and therefore has length 5 now (instead of 4+1+5+1=10).
+%
+% Eventualy we will have a verbose \blablanamespace and the difference between core
+% and regular can go ... after all, \xxxparameter can already clash between the two
+% prefix groups .. if users use this mechanism a lot they should use verbose names
+% anyway (the old two character names were mostly an optimization as they also
+% expanded to these characters).
+
+% todo: register namespaces at lua end for logging and reverse resolve
+% todo: move this to syst-ini so that we can use it real early
+
+\newcount\c_mult_interfaces_n_of_namespaces
+
+%def\v_interfaces_prefix_template{\number \c_mult_interfaces_n_of_namespaces>}
+%def\v_interfaces_prefix_template{\characters\c_mult_interfaces_n_of_namespaces>}
+
+%def\v_interfaces_prefix_template % consistently %03i>
+% {\ifnum\c_mult_interfaces_n_of_namespaces<\plusten00\else\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi\fi
+% \number\c_mult_interfaces_n_of_namespaces>}
+
+\def\v_interfaces_prefix_template
+ {\number\c_mult_interfaces_n_of_namespaces>}
+
+\unexpanded\def\installnamespace#1% for modules and users
+ {\ifcsname ????#1\endcsname
+ \writestatus\m!system{duplicate user namespace '#1'}\wait
+ \else
+ \global\advance\c_mult_interfaces_n_of_namespaces\plusone
+ \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}%
+ \fi}
+
+\unexpanded\def\installcorenamespace#1%
+ {\ifcsname ??#1\endcsname
+ \writestatus\m!system{duplicate core namespace '#1'}\wait
+ \else
+ \global\advance\c_mult_interfaces_n_of_namespaces\plusone
+ \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}%
+ \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}%
+ \fi}
+
+\def\mult_interfaces_get_parameters_error_indeed#1#2%
+ {\clf_showassignerror{#1}{#2}\inputlineno} % no longer \waitonfatalerror
+
+% We install two core namespaces here, as we want nice error messages. Maybe
+% we will reserve the first 9.
+
+\installcorenamespace{fontinstanceready}
+\installcorenamespace{fontinstancebasic}
+\installcorenamespace{fontinstanceclass}
+
+%D The next one is handy for local assignments.
+
+\installcorenamespace{dummy}
+
+\letvalue\??dummy\empty
+
+ \def\dummyparameter #1{\begincsname\??dummy#1\endcsname}
+ \def\directdummyparameter #1{\begincsname\??dummy#1\endcsname}
+\unexpanded\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname}
+\unexpanded\def\setexpandeddummyparameter#1{\expandafter\edef\csname\??dummy#1\endcsname}
+\unexpanded\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname}
+
+% \unexpanded\def\getdummyparameters
+% {\mult_interfaces_get_parameters\??dummy}
+
+\unexpanded\def\getdummyparameters[#1%
+ {\if\noexpand#1]%
+ \expandafter\gobbleoneargument
+ \else
+ \let\m_mult_interfaces_namespace\??dummy
+ \expandafter\mult_interfaces_get_parameters_indeed
+ \fi#1}
+
+\mult_interfaces_install_style_and_color_handler
+ \directdummyparameter
+ \usedummystyleandcolor
+ \usedummystyleparameter
+ \usedummycolorparameter
+
+% Maybe a \definecorenamespace[name][directparameter,directsetup][parent] but we
+% don't gain much. Actually we might just inline all definitions.
+
+% \enabletrackers[interfaces.namespaces,context.flush]
+%
+% \definenamespace
+% [xy]
+% [type=module,
+% comment=test module,
+% version=1,
+% name=test,
+% style=yes,
+% command=yes,
+% setup=list,
+% set=yes,
+% parent=xy]
+%
+% \unprotect
+% \getparameters
+% [\????xy]
+% [text=]
+% \protect
+%
+% \definetest[one]
+%
+% \starttext
+%
+% “\testparameter{text}”
+%
+% \setuptest[text=foo]
+%
+% “\testparameter{text}”
+%
+% \setuptest[one][text=bar]
+%
+% “\testparameter{text}”
+%
+% \stoptext
+%
+% This is a user (module) command:
+
+\unexpanded\def\definenamespace
+ {\dodoubleargument\mult_interfaces_define_name_space}
+
+\def\mult_interfaces_define_name_space[#1][#2]% namespace settings
+ {\clf_definenamespace{#1}{#2}}
+
+\def\listnamespaces
+ {\clf_listnamespaces}
+
+%D Helper:
+%D
+%D \starttyping
+%D \showparentchain{@@am}{left}
+%D \stoptyping
+
+\unexpanded\def\showparentchain#1#2%
+ {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}
+
+% \def\mult_interfaces_show_parent_chain#1%
+% {#1 => %
+% \ifcsname#1:\s!parent\endcsname
+% \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
+% \fi}
+
+\def\mult_interfaces_show_parent_chain#1%
+ {#1 => %
+ \ifcsname#1:\s!parent\endcsname
+ %\expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
+ \expandafter\mult_interfaces_show_parent_chain\lastnamedcs
+ \fi}
+
+%D Another helper (needs to be applied):
+
+\unexpanded\def\doifelsecommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifcommandhandlerelse\doifelsecommandhandler
+
+\unexpanded\def\doifcommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotcommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\let\doifcommandhandlerelse\doifelsecommandhandler
+
+% another set of (fast) helpers (grep for usage):
+
+\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy
+ {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3}
+
+\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy
+ {#1\endcsname#1\else#2\fi\endcsname}
+
+\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
+ {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
+
+\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
+ {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}}
+
+\def\syst_helpers_expand_checked_value#1#2%
+ {#1\endcsname#1\else#2\fi\endcsname}
+
+%D Conventions:
+%D
+%D \starttyping
+%D \newcount \c_class_whatever
+%D \newconditional \c_class_whatever
+%D \newconstant \c_class_whatever
+%D \newdimen \d_class_whatever
+%D \newskip \s_class_whatever
+%D \newmuskip \s_class_whatever
+%D \newbox \b_class_whatever
+%D \newtoks \t_class_whatever
+%D
+%D \edef\p_class_whatever{\classparameter\c!whatever}
+%D \edef\m_class_whatever{whatever}
+%D \stoptyping
+
+% experiment: in principle this is faster but not that noticeable as we don't do that
+% many assignments and mechanism that do are also slow; the advantage is mostly nicer
+% in tracing
+
+\def\s!simple{simple}
+\def\s!single{single}
+\def\s!double{double}
+\def\s!triple{triple}
+
+\let\c_mult_set\relax
+
+\unexpanded\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7%
+ {\newcount#3%
+ \let#6\empty
+ \unexpanded\def#2%
+ {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname
+ \ifx\c_mult_set\relax
+ \expandafter\newtoks\c_mult_set
+ \expandafter\let\csname #1_t_#6\endcsname\c_mult_set
+ \fi}
+ \unexpanded\def#4##1%
+ {\pushmacro#6%
+ \advance#3\plusone
+ \edef#6{##1}%
+ \unprotect}%
+ \unexpanded\def#5%
+ {\protect
+ \advance#3\minusone
+ \popmacro#6}%
+ \unexpanded\def#7##1%
+ {\edef#6{##1}%
+ #2%
+ \the\c_mult_set\relax}}
+
+\unexpanded\def\installdefinitionset#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_definition_set
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname set_#2_toks\endcsname
+ \expandafter\noexpand\csname #2_nesting_depth\endcsname
+ \expandafter\noexpand\csname push#2\endcsname
+ \expandafter\noexpand\csname pop#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname use#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc
+ {\let#5#2%
+ \unexpanded\def#2%
+ {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}%
+ \unexpanded\def#6%
+ {\dodoubleempty#7}%
+ \unexpanded\def#7[##1][##2]%
+ {\ifsecondargument
+ %#3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}%
+ #3\toksapp\c_mult_set{#9[##1][##2]}%
+ \orelse\iffirstargument
+ %#3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}%
+ #3\toksapp\c_mult_set{#8[##1]}%
+ \fi}}
+
+\unexpanded\def\installdefinitionsetmember#1#2#3#4%
+ {\normalexpanded
+ {\mult_interfaces_install_definition_set_member
+ {\noexpand#3}% \??aa
+ \expandafter\noexpand\csname setup#4\endcsname
+ \expandafter\noexpand\csname set_#2_toks\endcsname
+ \expandafter\noexpand\csname #2_nesting_depth\endcsname
+ \expandafter\noexpand\csname normal_setup_#4\endcsname
+ \expandafter\noexpand\csname delayed_setup_#4\endcsname
+ \expandafter\noexpand\csname do_delayed_setup_#4\endcsname
+ \expandafter\noexpand\csname setup#4_\s!single\endcsname
+ \expandafter\noexpand\csname setup#4_\s!double\endcsname}}
+
+%D Another experiment:
+
+\unexpanded\def\mult_interfaces_install_parent_injector#1#2#3#4%
+ {\unexpanded\def#4##1%
+ {\ifx#3\empty
+ \expandafter\def\csname#1#2:\s!parent\endcsname{#1##1}%
+ \fi}}
+
+\unexpanded\def\installparentinjector#1#2%
+ {\normalexpanded{\mult_interfaces_install_parent_injector
+ {\noexpand#1}%
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname current#2parent\endcsname
+ \expandafter\noexpand\csname inject#2parent\endcsname}}
+
+% Faster but not used that much to make a dent in performance. But, because it's
+% cleaner anyway and also gives less tracing, we apply it a few times.
+
+\unexpanded\def\syst_helpers_install_macro_stack#1#2#3%
+ {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+ \ifcsname#3\m_syst_helpers_push_macro\endcsname\else
+ \expandafter\newcount\csname#3\m_syst_helpers_push_macro\endcsname
+ \expandafter\edef\csname push_macro_\m_syst_helpers_push_macro\endcsname
+ {\noexpand\expandafter\glet
+ \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname
+ \noexpand#1%
+ \global\advance\csname#3\m_syst_helpers_push_macro\endcsname\plusone}%
+ \expandafter\edef\csname pop_macro_\m_syst_helpers_push_macro\endcsname
+ {\global\advance\csname#3\m_syst_helpers_push_macro\endcsname\minusone
+ \noexpand\expandafter#2%
+ \noexpand\expandafter\noexpand#1%
+ \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname}%
+ \fi}
+
+\unexpanded\def\installmacrostack #1{\syst_helpers_install_macro_stack#1\let \??localpushedmacro }
+\unexpanded\def\installglobalmacrostack#1{\syst_helpers_install_macro_stack#1\glet\??globalpushedmacro}
+
+% \unprotect
+%
+% \installcorenamespace {test} \installcommandhandler \??test {test} \??test
+% \unexpanded\def\TestMeA[#1]%
+% {\edef\currenttest{#1}
+% \edef\p_before{\testparameter\c!before}%
+% \ifx\p_before\empty \relax \else \relax \fi}
+% \unexpanded\def\TestMeB[#1]%
+% {\edef\currenttest{#1}
+% \doifelsenothing{\testparameter\c!before}\relax\relax}
+% \unexpanded\def\TestMeC[#1]%
+% {\edef\currenttest{#1}
+% \expandafter\expandafter\expandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi}
+% \unexpanded\def\TestMeD[#1]%
+% {\edef\currenttest{#1}
+% \doubleexpandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi}
+%
+% \protect
+%
+% \starttext
+% \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed]
+% \testfeatureonce{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502
+% \testfeatureonce{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530
+% \testfeatureonce{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487
+% \testfeatureonce{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493
+% \stoptext
+
+% There is no real demand for this ... even if this is two to three times as fast we
+% only gain a few milliseconds:
+%
+% \starttyping
+% \unexpanded\def\foo#1{[foo:#1]}
+%
+% \installcommalistprocessor {foo} \foo
+% \installcommalistprocessorcommand \processfoolist \foo
+%
+% \infofont
+%
+% \commalistprocessor{foo}[a,b,c,{x,y,z},d]\par
+% \processfoolist[a, b, c, {x,y,z}, d]\par
+% \processcommalist[{x,y,z}]\foo\blank
+%
+% \commalistprocessor{foo}[{x,y,z},a]\par
+% \commalistprocessor{foo}[{x,y,z}]\par
+% \processfoolist[{x,y,z},a]\par
+% \processfoolist[{x,y,z}]\par
+% \processcommalist[{x,y,z}]\foo\blank
+%
+% \unexpanded\def\foo#1{}
+%
+% \testfeatureonce{400000}{\processfoolist [fixed,middle,bar]} \elapsedtime\quad
+%%\testfeatureonce{400000}{\commalistprocessor{foo}[fixed,middle,bar]} \elapsedtime\quad
+% \testfeatureonce{400000}{\processcommalist [fixed,middle,bar]\foo} \elapsedtime\quad
+% \stoptyping
+%
+% For instance the luatex manual only has some 3000 calls. But I keep this around as one
+% never knows when we might need it.
+
+\installcorenamespace{commalistprocessor}
+\installcorenamespace{commalistprocessorwrap}
+\installcorenamespace{commalistprocessorfirst}
+\installcorenamespace{commalistprocessornext}
+\installcorenamespace{commalistprocessoraction}
+
+\unexpanded\def\installcommalistprocessor#1#2% 5 macro names overhead
+ {\unexpanded\expandafter\edef\csname\??commalistprocessor#1\endcsname[%
+ % {\noexpand\futureexpandis]%
+ % \noexpand\gobbleoneargument
+ % \csname\??commalistprocessorpickup#1\endcsname}
+ %\unexpanded\expandafter\edef\csname\??commalistprocessorpickup#1\endcsname
+ {\csname\??commalistprocessorwrap#1\endcsname\relax}% \relax preserves {}
+ \unexpanded\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]%
+ {\csname\??commalistprocessorfirst#1\endcsname##1,]}
+ \unexpanded\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname\relax
+ {\csname\??commalistprocessornext#1\endcsname}%
+ \unexpanded\expandafter\edef\csname\??commalistprocessornext#1\endcsname
+ {\noexpand\futureexpandis]%
+ \noexpand\gobbleoneargument
+ \csname\??commalistprocessoraction#1\endcsname}
+ \unexpanded\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,%
+ {\noexpand#2{##1}%
+ \csname\??commalistprocessornext#1\endcsname}}
+
+\unexpanded\def\installcommalistprocessorcommand#1#2% \processor \action
+ {\edef\p_name{\csstring#2}%
+ \installcommalistprocessor\p_name{#2}%
+ \expandafter\let\expandafter#1\csname\??commalistprocessor\p_name\endcsname}
+
+\unexpanded\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua
index 5222ea84f..bce5f9d83 100644
--- a/tex/context/base/mkiv/mult-def.lua
+++ b/tex/context/base/mkiv/mult-def.lua
@@ -9560,6 +9560,10 @@ return {
["en"]="order",
["nl"]="volgorde",
},
+ ["anchoring"]={
+ ["en"]="anchoring",
+ ["nl"]="verankering",
+ },
["orientation"]={
["cs"]="orientation",
["de"]="orientation",
diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua
index 846380027..540b1cfba 100644
--- a/tex/context/base/mkiv/mult-low.lua
+++ b/tex/context/base/mkiv/mult-low.lua
@@ -41,7 +41,7 @@ return {
"bgroup", "egroup",
"endline",
--
- "conditionaltrue", "conditionalfalse",
+ "conditionaltrue", "conditionalfalse", "quitcondition",
--
"attributeunsetvalue",
--
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 76c357e2e..1f0f91311 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -25,8 +25,6 @@ return {
"fontcharht",
"fontcharic",
"fontcharwd",
- "futureexpand",
- "futureexpandis",
"glueexpr",
"glueshrink",
"glueshrinkorder",
@@ -221,6 +219,7 @@ return {
"Uunderdelimiter",
"Uvextensible",
"adjustspacing",
+ "aftergrouped",
"alignmark",
"aligntab",
"attribute",
@@ -232,6 +231,7 @@ return {
"boundary",
"boxdirection",
"boxorientation",
+ "boxtotal",
"boxxmove",
"boxxoffset",
"boxymove",
@@ -258,6 +258,9 @@ return {
"fontid",
"formatname",
"frozen",
+ "futureexpand",
+ "futureexpandis",
+ "futureexpandisap",
"gleaders",
"glet",
"glyphdatafield",
@@ -328,7 +331,6 @@ return {
"mathsurroundmode",
"mathsurroundskip",
"noboundary",
- "noexpand",
"nohrule",
"nokerns",
"noligs",
@@ -676,6 +678,7 @@ return {
"muskipdef",
"newlinechar",
"noalign",
+ "noexpand",
"noindent",
"nolimits",
"nonscript",
diff --git a/tex/context/base/mkiv/mult-sys.mkiv b/tex/context/base/mkiv/mult-sys.mkiv
index bd8fc80ff..14619316e 100644
--- a/tex/context/base/mkiv/mult-sys.mkiv
+++ b/tex/context/base/mkiv/mult-sys.mkiv
@@ -367,6 +367,7 @@
\definesystemconstant {marker}
\definesystemconstant {kernpairs}
\definesystemconstant {mixedcolumn}
+\definesystemconstant {orientation}
\definesystemconstant {ampersand}
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index 0764ee7e3..d60727eee 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -231,163 +231,163 @@ if not nuts.has_dimensions then
end
-local getfield = direct.getfield
-local setfield = direct.setfield
-
-nuts.getfield = getfield
-nuts.setfield = setfield
-
-nuts.getnext = direct.getnext
-nuts.setnext = direct.setnext
-
-nuts.getid = direct.getid
-
-nuts.getprev = direct.getprev
-nuts.setprev = direct.setprev
-
-local get_attribute = direct.get_attribute
-local set_attribute = direct.set_attribute
-local unset_attribute = direct.unset_attribute
-
-nuts.getattr = get_attribute
-nuts.setattr = set_attribute
-nuts.takeattr = unset_attribute -- ?
-
-nuts.is_zero_glue = direct.is_zero_glue
-nuts.effective_glue = direct.effective_glue
-
-nuts.getglue = direct.getglue
-nuts.setglue = direct.setglue
-nuts.getboxglue = direct.getglue
-nuts.setboxglue = direct.setglue
-
-nuts.getdisc = direct.getdisc
-nuts.setdisc = direct.setdisc
-nuts.getdiscretionary = direct.getdisc
-nuts.setdiscretionary = direct.setdisc
-
-nuts.getpre = direct.getpre
-nuts.setpre = direct.setpre
-nuts.getpost = direct.getpost
-nuts.setpost = direct.setpost
-nuts.getreplace = direct.getreplace
-nuts.setreplace = direct.setreplace
-
-local getdata = direct.getdata
-local setdata = direct.setdata
-
-nuts.getdata = getdata
-nuts.setdata = setdata
-nuts.getvalue = getdata
-nuts.setvalue = setdata
-
-nuts.getexpansion = direct.getexpansion
-nuts.setexpansion = direct.setexpansion
-
-nuts.getwhd = direct.getwhd
-nuts.setwhd = direct.setwhd
-nuts.getwidth = direct.getwidth
-nuts.setwidth = direct.setwidth
-nuts.getheight = direct.getheight
-nuts.setheight = direct.setheight
-nuts.getdepth = direct.getdepth
-nuts.setdepth = direct.setdepth
-nuts.getshift = direct.getshift
-nuts.setshift = direct.setshift
+local getfield = direct.getfield
+local setfield = direct.setfield
+
+nuts.getfield = getfield
+nuts.setfield = setfield
+
+nuts.getnext = direct.getnext
+nuts.setnext = direct.setnext
+
+nuts.getid = direct.getid
+
+nuts.getprev = direct.getprev
+nuts.setprev = direct.setprev
+
+local get_attribute = direct.get_attribute
+local set_attribute = direct.set_attribute
+local unset_attribute = direct.unset_attribute
+
+nuts.getattr = get_attribute
+nuts.setattr = set_attribute
+nuts.takeattr = unset_attribute -- ?
+
+nuts.is_zero_glue = direct.is_zero_glue
+nuts.effective_glue = direct.effective_glue
+
+nuts.getglue = direct.getglue
+nuts.setglue = direct.setglue
+nuts.getboxglue = direct.getglue
+nuts.setboxglue = direct.setglue
+
+nuts.getdisc = direct.getdisc
+nuts.setdisc = direct.setdisc
+nuts.getdiscretionary = direct.getdisc
+nuts.setdiscretionary = direct.setdisc
+
+nuts.getpre = direct.getpre
+nuts.setpre = direct.setpre
+nuts.getpost = direct.getpost
+nuts.setpost = direct.setpost
+nuts.getreplace = direct.getreplace
+nuts.setreplace = direct.setreplace
+
+local getdata = direct.getdata
+local setdata = direct.setdata
+
+nuts.getdata = getdata
+nuts.setdata = setdata
+nuts.getvalue = getdata
+nuts.setvalue = setdata
+
+nuts.getexpansion = direct.getexpansion
+nuts.setexpansion = direct.setexpansion
+
+nuts.getwhd = direct.getwhd
+nuts.setwhd = direct.setwhd
+nuts.getwidth = direct.getwidth
+nuts.setwidth = direct.setwidth
+nuts.getheight = direct.getheight
+nuts.setheight = direct.setheight
+nuts.getdepth = direct.getdepth
+nuts.setdepth = direct.setdepth
+nuts.getshift = direct.getshift
+nuts.setshift = direct.setshift
-- lmtx compatibility
-nuts.getorientation = direct.getorientation or function() end
-nuts.setorientation = direct.setorientation or function() end
+nuts.getorientation = direct.getorientation or function() end
+nuts.setorientation = direct.setorientation or function() end
-nuts.getglyphdata = direct.getglyphdata or get_attribute
-nuts.setglyphdata = direct.setglyphdata or function(n,d) set_attribute(n,0,d) end
+nuts.getglyphdata = direct.getglyphdata or get_attribute
+nuts.setglyphdata = direct.setglyphdata or function(n,d) set_attribute(n,0,d) end
-nuts.getruledata = direct.getglyphdata and getdata or function(n) return getfield(n,"transform") end
-nuts.setruledata = direct.setglyphdata and setdata or function(n,d) return setfield(n,"transform",d) end
+nuts.getruledata = direct.getglyphdata and getdata or function(n) return getfield(n,"transform") end
+nuts.setruledata = direct.setglyphdata and setdata or function(n,d) return setfield(n,"transform",d) end
-- so far
-nuts.getnucleus = direct.getnucleus
-nuts.setnucleus = direct.setnucleus
-nuts.getsup = direct.getsup
-nuts.setsup = direct.setsup
-nuts.getsub = direct.getsub
-nuts.setsub = direct.setsub
-
-nuts.getchar = direct.getchar
-nuts.setchar = direct.setchar
-nuts.getfont = direct.getfont
-nuts.setfont = direct.setfont
-nuts.getfam = direct.getfam
-nuts.setfam = direct.setfam
-
-nuts.getboth = direct.getboth
-nuts.setboth = direct.setboth
-nuts.setlink = direct.setlink
-nuts.setsplit = direct.setsplit
-
-nuts.getlist = direct.getlist -- only hlist and vlist !
-nuts.setlist = direct.setlist
-nuts.getleader = direct.getleader
-nuts.setleader = direct.setleader
-nuts.getcomponents = direct.getcomponents
-nuts.setcomponents = direct.setcomponents
-
-nuts.getsubtype = direct.getsubtype
-nuts.setsubtype = direct.setsubtype
-
-nuts.getlang = direct.getlang
-nuts.setlang = direct.setlang
-nuts.getlanguage = direct.getlang
-nuts.setlanguage = direct.setlang
-
-nuts.getattrlist = direct.getattributelist
-nuts.setattrlist = direct.setattributelist
-nuts.getattributelist = direct.getattributelist
-nuts.setattributelist = direct.setattributelist
-
-nuts.getoffsets = direct.getoffsets
-nuts.setoffsets = direct.setoffsets
-
-nuts.getkern = direct.getkern
-nuts.setkern = direct.setkern
-
-nuts.getdir = direct.getdir
-nuts.setdir = direct.setdir
-
-nuts.getdirection = direct.getdirection
-nuts.setdirection = direct.setdirection
-
-nuts.getpenalty = direct.getpenalty
-nuts.setpenalty = direct.setpenalty
-
-nuts.getbox = direct.getbox
-nuts.setbox = direct.setbox
-
-nuts.ischar = direct.is_char
-nuts.isglyph = direct.is_glyph
-
-----.is_char = nuts.ischar
-----.is_glyph = nuts.isglyph
-
-local d_remove_node = direct.remove
-local d_flush_node = direct.flush_node
-local d_getnext = direct.getnext
-local d_getprev = direct.getprev
-local d_getid = direct.getid
-local d_getlist = direct.getlist
-local d_find_tail = direct.tail
-local d_insert_after = direct.insert_after
-local d_insert_before = direct.insert_before
-local d_slide = direct.slide
------ d_copy_node = direct.copy
-local d_traverse = direct.traverse
-local d_setlink = direct.setlink
-local d_setboth = direct.setboth
-local d_getboth = direct.getboth
-
-local remove = (CONTEXTLMTXMODE > 0 and LUATEXFUNCTIONALITY >= 20190704) and d_remove_node or function(head,current,free_too)
+nuts.getnucleus = direct.getnucleus
+nuts.setnucleus = direct.setnucleus
+nuts.getsup = direct.getsup
+nuts.setsup = direct.setsup
+nuts.getsub = direct.getsub
+nuts.setsub = direct.setsub
+
+nuts.getchar = direct.getchar
+nuts.setchar = direct.setchar
+nuts.getfont = direct.getfont
+nuts.setfont = direct.setfont
+nuts.getfam = direct.getfam
+nuts.setfam = direct.setfam
+
+nuts.getboth = direct.getboth
+nuts.setboth = direct.setboth
+nuts.setlink = direct.setlink
+nuts.setsplit = direct.setsplit
+
+nuts.getlist = direct.getlist -- only hlist and vlist !
+nuts.setlist = direct.setlist
+nuts.getleader = direct.getleader
+nuts.setleader = direct.setleader
+nuts.getcomponents = direct.getcomponents
+nuts.setcomponents = direct.setcomponents
+
+nuts.getsubtype = direct.getsubtype
+nuts.setsubtype = direct.setsubtype
+
+nuts.getlang = direct.getlang
+nuts.setlang = direct.setlang
+nuts.getlanguage = direct.getlang
+nuts.setlanguage = direct.setlang
+
+nuts.getattrlist = direct.getattributelist
+nuts.setattrlist = direct.setattributelist
+nuts.getattributelist = direct.getattributelist
+nuts.setattributelist = direct.setattributelist
+
+nuts.getoffsets = direct.getoffsets
+nuts.setoffsets = direct.setoffsets
+
+nuts.getkern = direct.getkern
+nuts.setkern = direct.setkern
+
+nuts.getdir = direct.getdir
+nuts.setdir = direct.setdir
+
+nuts.getdirection = direct.getdirection
+nuts.setdirection = direct.setdirection
+
+nuts.getpenalty = direct.getpenalty
+nuts.setpenalty = direct.setpenalty
+
+nuts.getbox = direct.getbox
+nuts.setbox = direct.setbox
+
+nuts.ischar = direct.is_char
+nuts.isglyph = direct.is_glyph
+
+----.is_char = nuts.ischar
+----.is_glyph = nuts.isglyph
+
+local d_remove_node = direct.remove
+local d_flush_node = direct.flush_node
+local d_getnext = direct.getnext
+local d_getprev = direct.getprev
+local d_getid = direct.getid
+local d_getlist = direct.getlist
+local d_find_tail = direct.tail
+local d_insert_after = direct.insert_after
+local d_insert_before = direct.insert_before
+local d_slide = direct.slide
+----- d_copy_node = direct.copy
+local d_traverse = direct.traverse
+local d_setlink = direct.setlink
+local d_setboth = direct.setboth
+local d_getboth = direct.getboth
+
+local remove = CONTEXTLMTXMODE > 0 and d_remove_node or function(head,current,free_too)
if current then
local h, c = d_remove_node(head,current)
if free_too then
diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua
index 7d95f8c4c..b904e54d6 100644
--- a/tex/context/base/mkiv/node-rul.lua
+++ b/tex/context/base/mkiv/node-rul.lua
@@ -124,6 +124,9 @@ local dimenfactor = fonts.helpers.dimenfactor
local splitdimen = number.splitdimen
local setmetatableindex = table.setmetatableindex
+local magicconstants = tex.magicconstants
+local running = magicconstants.running
+
--
local striprange = nuts.striprange
@@ -773,9 +776,9 @@ interfaces.implement {
},
actions = function(t)
local n = new_rule(
- t.width,
- t.height,
- t.depth
+ t.width or running,
+ t.height or running,
+ t.depth or running
)
setattrlist(n,true)
setoffsets(n,t.xoffset,t.yoffset) -- ,t.left, t.right
diff --git a/tex/context/base/mkiv/pack-rul.mkiv b/tex/context/base/mkiv/pack-rul.mkiv
index 34db6eec1..8de68f248 100644
--- a/tex/context/base/mkiv/pack-rul.mkiv
+++ b/tex/context/base/mkiv/pack-rul.mkiv
@@ -43,24 +43,6 @@
\def\pack_framed_setup_line_width[#1]%
{\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
-% %D \macros
-% %D {setupscreens}
-% %D
-% %D Sort of obsolete:
-% %D
-% %D \showsetup{setupscreens}
-%
-% \installcorenamespace{screens}
-%
-% \installsetuponlycommandhandler \??screens {screens}
-%
-% \appendtoks
-% \edef\defaultbackgroundscreen{\directscreensparameter\c!screen}
-% \to \everysetupscreens
-%
-% \setupscreens
-% [\c!screen=.90] % was .95 but that's hardly visible
-
%D The parameter handler:
\installcorenamespace{framed}
@@ -356,18 +338,6 @@
% \quad}
% \stopTEXpage
-%D The oval box is drawn using a special macro, depending on
-%D the driver in use.
-
-% \def\pack_framed_background_box_gray % avoid black rules when no gray
-% {\edef\p_framed_backgroundscreen{\framedparameter\c!backgroundscreen}%
-% \ifx\p_framed_backgroundscreen\empty \else
-% \pack_framed_background_box_gray_indeed
-% \fi}
-%
-% \def\pack_framed_background_box_gray_indeed % can be more direct but who cares, just compatibility
-% {\colored[s=\p_framed_backgroundscreen]{\pack_framed_filled_box}}
-
%D It won't be a surprise that we not only provide gray boxes, but also colored
%D ones. Here it is:
@@ -577,21 +547,6 @@
\box\b_framed_extra
\egroup}
-% \def\pack_framed_process_background_indeed_external#1%
-% {\pack_framed_overlay_initialize
-% \bgroup
-% \setbox\b_framed_extra\hpack\bgroup
-% \ifzeropt\framedbackgroundoffset\else
-% \kern-\framedbackgroundoffset
-% \fi
-% \hbox\bgroup#1\egroup
-% \egroup
-% \wd\b_framed_extra\zeropoint
-% \ht\b_framed_extra\framedbackgroundheight
-% \dp\b_framed_extra\framedbackgrounddepth
-% \box\b_framed_extra
-% \egroup}
-
\def\pack_framed_process_background_indeed_external
{\pack_framed_overlay_initialize
\pack_framed_process_background_indeed_internal}
@@ -619,13 +574,6 @@
\edef\m_overlay_region{\reservedautoregiontag}%
\fi}
-% \def\pack_framed_add_region % experiment
-% {\ifx\m_overlay_region\v!yes
-% \anch_mark_region_box\b_framed_normal
-% \else
-% \anch_mark_tagged_box\b_framed_normal\m_overlay_region
-% \fi}
-
\def\pack_framed_add_region % experiment
{\anch_mark_tagged_box\b_framed_normal\m_overlay_region}
@@ -654,18 +602,6 @@
\hss
\egroup}}
-% \def\pack_framed_overlay_initialize_indeed
-% {\edef\overlaywidth {\the\d_framed_target_wd\space}%
-% \edef\overlayheight {\the\dimexpr\d_framed_target_ht+\d_framed_target_dp\relax\space}%
-% \edef\overlaydepth {\the\d_framed_target_dp\space}%
-% \edef\overlaycolor {\framedparameter\c!backgroundcolor}% let ?
-% \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers
-% \edef\overlaylinewidth{\the\d_framed_linewidth\space}%
-% %\edef\overlaycorner {\framedparameter\c!backgroundcorner}%
-% %\edef\overlayradius {\framedparameter\c!backgroundradius}%
-% \edef\overlayoffset {\the\framedbackgroundoffset\space}% \backgroundoffset % we steal this one
-% \let\pack_framed_overlay_initialize\relax}
-
\def\pack_framed_overlay_initialize_indeed
{\d_overlay_width \d_framed_target_wd
\d_overlay_height \dimexpr\d_framed_target_ht+\d_framed_target_dp\relax
@@ -719,27 +655,6 @@
\box\b_framed_normal
\box\b_framed_extra}}
-% \def\pack_framed_stroked_box_normal
-% {\setbox\scratchbox\emptyhbox
-% \wd\scratchbox\d_framed_target_wd
-% \ht\scratchbox\d_framed_target_ht
-% \dp\scratchbox\d_framed_target_dp
-% \setbox\scratchbox\vpack \bgroup
-% \csname \??framedtop\p_framed_frame\framedparameter\c!topframe \endcsname
-% \nointerlineskip % new (needed for fences)
-% \hbox \bgroup
-% \csname \??framedleft\p_framed_frame\framedparameter\c!leftframe \endcsname
-% \box\scratchbox
-% \csname \??framedright\p_framed_frame\framedparameter\c!rightframe \endcsname
-% \egroup
-% \nointerlineskip % new (needed for fences)
-% \csname \??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname
-% \egroup
-% \wd\scratchbox\d_framed_target_wd
-% \ht\scratchbox\d_framed_target_ht
-% \dp\scratchbox\d_framed_target_dp
-% \box\scratchbox}
-
\def\pack_framed_stroked_box_normal_opened
{\setbox\scratchbox\vpack \bgroup
\csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname
@@ -885,35 +800,6 @@
\newcount\c_pack_framed_nesting
-% to be tested (slightly more efficient):
-%
-% \unexpanded\def\pack_frame_common % #1 #2
-% {\bgroup
-% \advance\c_pack_framed_nesting\plusone
-% \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
-% \edef\currentframed{>\the\c_pack_framed_nesting}%
-% \pack_framed_initialize
-% \bgroup
-% \doifnextoptionalcselse} % #1 #2
-%
-% \unexpanded\def\framed {\pack_frame_common\pack_framed_process_framed_pickup\pack_framed_process_indeed}
-% \unexpanded\def\startframed{\pack_frame_common\pack_framed_start_framed_pickup \pack_framed_start_indeed }
-%
-% \def\pack_framed_process_framed_pickup[#1]%
-% {\setupcurrentframed[#1]%
-% \pack_framed_process_indeed}
-%
-% \def\pack_framed_start_framed_pickup[#1]%
-% {\setupcurrentframed[#1]% here !
-% \secondargumenttrue % dirty trick
-% \pack_framed_start_framed_indeed}
-%
-% \def\pack_framed_start_framed_indeed
-% {\pack_framed_process_indeed
-% \bgroup}
-%
-% no longer .. we also accept \startframed[tag]
-
\unexpanded\def\pack_framed_process_framed[#1]%
{\bgroup
\iffirstargument % faster
@@ -929,24 +815,6 @@
\pack_framed_initialize
\dosingleempty\pack_framed_process_framed}
-% \unexpanded\def\startframed
-% {\dosingleempty\pack_framed_start_framed}
-%
-% \def\pack_framed_start_framed[#1]%
-% {\bgroup
-% \advance\c_pack_framed_nesting\plusone
-% \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
-% \edef\currentframed{>\the\c_pack_framed_nesting}%
-% \pack_framed_initialize
-% \bgroup
-% \iffirstargument
-% \secondargumenttrue % dirty trick
-% \setupcurrentframed[#1]% here !
-% \fi
-% \pack_framed_process_indeed
-% \bgroup
-% \ignorespaces}
-
\unexpanded\def\startframed
{\dosingleempty\pack_framed_start_framed}
@@ -1928,30 +1796,6 @@
% \framed[width=12cm,height=3cm,orientation=-180]{\input ward\relax}
% \framed[width=12cm,height=3cm,orientation=-270]{\input ward\relax}
-% \def\pack_framed_start_orientation
-% {\ifcase\p_framed_orientation
-% \let\pack_framed_stop_orientation\relax
-% \else
-% \scratchcounter\p_framed_orientation % weird .. why
-% \divide\scratchcounter\plustwo
-% \ifodd\scratchcounter
-% \let\pack_framed_stop_orientation\pack_framed_stop_orientation_odd
-% \else
-% \let\pack_framed_stop_orientation\pack_framed_stop_orientation_even
-% \fi
-% \fi}
-%
-% \def\pack_framed_stop_orientation_odd
-% {\swapmacros\framedwidth\framedheight
-% \swapmacros\localwidth\localheight
-% \swapdimens\d_framed_height\d_framed_width
-% \pack_framed_stop_orientation_even}
-%
-% \def\pack_framed_stop_orientation_even
-% {\setbox\b_framed_normal\hbox{\dorotatebox\p_framed_orientation\hbox{\box\b_framed_normal}}%
-% \d_framed_height\ht\b_framed_normal
-% \d_framed_width \wd\b_framed_normal}
-
\def\pack_framed_start_orientation
{\ifcase\p_framed_orientation
\let\pack_framed_stop_orientation\relax
@@ -2042,15 +1886,6 @@
\edef\currentmathframed{#1}%
\dosingleempty\pack_framed_mathframed_indeed}
-% \def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
-% {\iffirstargument
-% \setupcurrentmathframed[#1]%
-% \fi
-% \c_framed_mstyle\mathstyle
-% \doifnot{\mathframedparameter\c!location}\v!low{\let\normalstrut\pack_framed_math_strut}%
-% \inheritedmathframedframed{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
-% \endgroup}
-
\newcount\c_pack_framed_mathframed
\newtoks \t_pack_framed_mathframed
diff --git a/tex/context/base/mkiv/pack-rul.mkxl b/tex/context/base/mkiv/pack-rul.mkxl
new file mode 100644
index 000000000..e21f5f1c2
--- /dev/null
+++ b/tex/context/base/mkiv/pack-rul.mkxl
@@ -0,0 +1,3049 @@
+%D \module
+%D [ file=pack-rul, % was core-rul,
+%D version=1998.10.16,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Ruled Content,
+%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.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Ruled Content}
+
+%D The code here is expanded lots of time as framed is used in many places. This is
+%D why the code here is (and gets) optimized as much as possible. Also, by avoiding
+%D packaging and expansion we also keep tracing reasonable. For instance, multiple
+%D stacked backgrounds can slow down a run if not optimized this way.
+
+\registerctxluafile{pack-rul}{optimize}
+
+\unprotect
+
+% \definesystemvariable {ol} % OmLijnd -> check scrn-fld too
+
+%D \macros
+%D {linewidth, setuplinewidth}
+%D
+%D This module deals with rules (lines) in several ways. First we introduce two
+%D macros that can be used to set some common characteristics.
+%D
+%D \showsetup{setuplinewidth}
+%D
+%D The linewidth is available in \type{\linewidth}. The preset value of .4pt equals
+%D the default hard coded \TEX\ rule width.
+
+\newdimen\linewidth
+
+\unexpanded\def\setuplinewidth
+ {\dosingleargument\pack_framed_setup_line_width}
+
+\def\pack_framed_setup_line_width[#1]%
+ {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
+
+%D The parameter handler:
+
+\installcorenamespace{framed}
+\installcorenamespace{framedtop}
+\installcorenamespace{framedbottom}
+\installcorenamespace{framedleft}
+\installcorenamespace{framedright}
+
+\installcorenamespace{regularframed}
+\installcorenamespace{simplifiedframed}
+
+\installcommandhandler \??framed {framed} \??framed
+
+\let\pack_framed_framedparameter \framedparameter
+\let\pack_framed_framedparameterhash\framedparameterhash
+\let\pack_framed_setupcurrentframed \setupcurrentframed
+
+\def\pack_framed_initialize
+ {\let\framedparameter \pack_framed_framedparameter
+ \let\framedparameterhash\pack_framed_framedparameterhash
+ \let\setupcurrentframed \pack_framed_setupcurrentframed
+ \inframedtrue}
+
+%D A helper:
+
+\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax}
+
+%D Inheritance:
+
+\def\installinheritedframed#1%
+ {\normalexpanded{\doinstallinheritedframed
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname #1parameter\endcsname
+ \expandafter\noexpand\csname #1parameterhash\endcsname
+ \expandafter\noexpand\csname do#1parameter\endcsname
+ \expandafter\noexpand\csname do#1parentparameter\endcsname
+ \expandafter\noexpand\csname do#1rootparameter\endcsname
+ \expandafter\noexpand\csname setupcurrent#1\endcsname
+ \expandafter\noexpand\csname inherited#1framed\endcsname
+ \expandafter\noexpand\csname inherited#1framedbox\endcsname}} % new
+
+\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9%
+ {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}%
+ %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root
+ \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root
+ \unexpanded\def#8%
+ {\bgroup
+ \bgroup
+ \inframedtrue
+ \let\currentframed #1%
+ \let\framedparameter #2%
+ \let\framedparameterhash#3%
+ \let\setupcurrentframed #7%
+ \pack_framed_process_indeed}%
+ \unexpanded\def#9%
+ {\bgroup
+ \inframedtrue
+ \let\currentframed #1%
+ \let\framedparameter #2%
+ \let\framedparameterhash#3%
+ \let\setupcurrentframed #7%
+ \pack_framed_process_box_indeed}}
+
+\unexpanded\def\installframedcommandhandler#1#2#3%
+ {\installcommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+\unexpanded\def\installframedautocommandhandler#1#2#3%
+ {\installautocommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+\unexpanded\def\installsimpleframedcommandhandler#1#2#3%
+ {\installsimplecommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+% for regular framed
+
+\setupframed
+ [\c!width=\v!fit,
+ \c!height=\v!broad,
+ %\c!minheight=\zeropoint,
+ %\c!lines=,
+ \c!offset=.25\exheight, % \defaultframeoffset
+ \c!empty=\v!no,
+ \c!frame=\v!on,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
+ \c!radius=.5\bodyfontsize,
+ \c!rulethickness=\linewidth,
+ \c!corner=\v!rectangular,
+ \c!depth=\zeropoint,
+ %\c!foregroundcolor=,
+ %\c!foregroundstyle=,
+ %\c!background=,
+ %\c!backgroundcolor=,
+ \c!backgroundoffset=\zeropoint,
+ %\c!framecolor=,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here
+ \c!backgroundradius=\framedparameter\c!radius,
+ \c!backgrounddepth=\framedparameter\c!depth,
+ \c!framecorner=\framedparameter\c!corner,
+ \c!frameradius=\framedparameter\c!radius,
+ \c!framedepth=\framedparameter\c!depth,
+ %\c!component=,
+ %\c!region=,
+ %\c!align=,
+ \c!bottom=\vss,
+ %\c!top=,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!yes,
+ \c!location=\v!normal,
+ %\c!orientation=,
+ %\c!anchoring=,
+ \c!autowidth=\v!yes,
+ %\c!setups=,
+ \c!loffset=\zeropoint,
+ \c!roffset=\zeropoint,
+ \c!toffset=\zeropoint,
+ \c!boffset=\zeropoint]
+
+%D For backgrounds and such:
+
+\defineframed
+ [\??simplifiedframed]
+ [\c!frame=\v!off,
+ \c!depth=\zeropoint,
+ \c!offset=\v!overlay,
+ \c!component=,
+ \c!region=,
+ \c!radius=.5\bodyfontsize,
+ \c!rulethickness=\linewidth,
+ \c!corner=\v!rectangular,
+ \c!backgroundoffset=\zeropoint,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here
+ \c!backgroundradius=\framedparameter\c!radius,
+ \c!backgrounddepth=\framedparameter\c!depth,
+ \c!framecorner=\framedparameter\c!corner,
+ \c!frameradius=\framedparameter\c!radius,
+ \c!framedepth=\framedparameter\c!depth,
+ \c!location=\v!normal,
+ \c!loffset=\zeropoint,
+ \c!roffset=\zeropoint,
+ \c!toffset=\zeropoint,
+ \c!boffset=\zeropoint]
+
+\unexpanded\def\definesimplifiedframed[#1]% no settings
+ {\defineframed[#1][\??simplifiedframed]%
+ \expandafter\let\csname#1\endcsname\undefined}
+
+\expandafter\let\csname\??simplifiedframed\endcsname\undefined
+
+%D We will communicate through module specific variables, current framed
+%D parameters and some reserved dimension registers.
+
+\newdimen\d_framed_target_wd
+\newdimen\d_framed_target_ht
+\newdimen\d_framed_target_dp
+\newdimen\d_framed_linewidth \let\ruledlinewidth\d_framed_linewidth % needed at lua end
+
+\let\p_framed_frame \empty % \framedparameter\c!frame
+\let\p_framed_backgroundoffset\empty
+\let\p_framed_foregroundstyle \empty
+\let\p_framed_autostrut \empty
+\let\p_framed_location \empty
+\let\p_framed_orientation \empty
+\let\p_framed_anchoring \empty
+\let\p_framed_autowidth \empty
+\let\p_framed_franalyze \empty
+\let\p_framed_backgroundcorner\empty
+\let\p_framed_backgroundradius\empty
+\let\p_framed_framecorner \empty
+\let\p_framed_frameradius \empty
+\let\p_framed_lines \empty
+\let\p_framed_empty \empty
+\let\p_framed_backgroundcolor \empty
+\let\p_framed_framecolor \empty
+\let\p_framed_component \empty
+\let\p_framed_background \empty
+\let\p_framed_rulethickness \empty
+\let\p_framed_foregroundcolor \empty
+\let\p_framed_setups \empty
+
+%D We don't have to stick to a \TEX\ drawn rule, but also can use rounded
+%D or even fancier shapes, as we will see later on.
+
+\def\pack_framed_filled_box
+ {\edef\p_framed_backgroundcorner{\framedparameter\c!backgroundcorner}%
+ \ifx\p_framed_backgroundcorner\v!rectangular
+ \pack_framed_filled_box_normal
+ \else
+ \pack_framed_filled_box_radius
+ \fi}
+
+\def\pack_framed_filled_box_normal
+ {\vrule
+ \s!width \d_framed_target_wd
+ \s!height\d_framed_target_ht
+ \s!depth \d_framed_target_dp
+ \relax}
+
+\def\pack_framed_filled_box_radius
+ {\edef\p_framed_backgroundradius{\framedparameter\c!backgroundradius}%
+ \ifzeropt\dimexpr\p_framed_backgroundradius\relax % just in case of .x\bodyfontsize
+ \pack_framed_filled_box_normal
+ \else
+ \pack_framed_filled_box_round
+ \fi}
+
+\def\pack_framed_filled_box_round
+ {\frule
+ type fill
+ width \d_framed_target_wd
+ height \d_framed_target_ht
+ depth \d_framed_target_dp
+ line \d_framed_linewidth
+ radius \p_framed_backgroundradius\space
+ corner {\p_framed_backgroundcorner}
+ \relax}
+
+\def\pack_framed_stroked_box
+ {\edef\p_framed_framecorner{\framedparameter\c!framecorner}%
+ \ifx\p_framed_framecorner\v!rectangular
+ \pack_framed_stroked_box_normal
+ \else
+ \pack_framed_stroked_box_radius
+ \fi}
+
+\def\pack_framed_stroked_box_radius
+ {\edef\p_framed_frameradius{\framedparameter\c!frameradius}%
+ \ifzeropt\dimexpr\p_framed_frameradius\relax % just in case of .x\bodyfontsize
+ \pack_framed_stroked_box_normal
+ \orelse\ifx\p_framed_frame\v!on
+ \pack_framed_stroked_box_round
+ \fi}
+
+% \pack_framed_stroked_box_normal % later
+
+\def\pack_framed_stroked_box_round
+ {\frule
+ width \d_framed_target_wd
+ height \d_framed_target_ht
+ depth \d_framed_target_dp
+ line \d_framed_linewidth
+ radius \p_framed_frameradius\space
+ corner {\p_framed_backgroundcorner}
+ \relax}
+
+% a lot of weird corners
+%
+% \startTEXpage
+% \dontleavehmode\framed
+% [corner=0,frame=on,framecolor=green,
+% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green,
+% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green,
+% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {9}{12}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{13}{16}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{17}{20}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{21}{24}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{25}{28}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \stopTEXpage
+
+%D It won't be a surprise that we not only provide gray boxes, but also colored
+%D ones. Here it is:
+
+\def\pack_framed_background_box_color
+ {\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}%
+ \ifx\p_framed_backgroundcolor\empty \else
+ \doifcolor\p_framed_backgroundcolor\pack_framed_background_box_color_indeed
+ \fi}
+
+\def\pack_framed_background_box_color_indeed
+ {\hpack{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}}
+
+%D \macros
+%D {defineoverlay, doifoverlayelse, overlayoffset,
+%D overlaywidth, overlayheight, overlaydepth,
+%D overlaycolor, overlaylinecolor, overlaylinewidth}
+%D
+%D Before we define the macro that actually takes card of the backgrounds, we
+%D introduce overlays. An overlay is something that contrary to its name lays {\em
+%D under} the text. An example of an overlay definition is:
+%D
+%D \startbuffer[tmp-1]
+%D \defineoverlay
+%D [fancy]
+%D [{\externalfigure
+%D [mp-cont.502]
+%D [width=\overlaywidth,
+%D height=\overlayheight]}]
+%D \stopbuffer
+%D
+%D \typebuffer[tmp-1]
+%D
+%D That for instance can be uses in:
+%D
+%D \startbuffer[tmp-2]
+%D \framed[backgroundachtergrond=fancy]{How Fancy!}
+%D \framed[backgroundachtergrond=fancy,frame=off]{Even More Fancy!}
+%D \stopbuffer
+%D
+%D and looks like:
+%D
+%D \startlinecorrection
+%D \vbox{\baselineskip24pt\getbuffer[tmp-1]\getbuffer[tmp-2]}
+%D \stoplinecorrection
+%D
+%D The formal definition is:
+%D
+%D \showsetup{defineoverlay}
+%D
+%D This macro's definition is a bit obscure, due the many non||used arguments and
+%D the two step call that enable the setting of the width, height and depth
+%D variables. Multiple backgrounds are possible and are specified as:
+%D
+%D \starttyping
+%D \framed[background={one,two,three}]{Three backgrounds!}
+%D \stoptyping
+%D
+%D Most drawing packages only know width and height. Therefore the dimensions have a
+%D slightly different meaning here:
+%D
+%D \startitemize[packed]
+%D \item \type{\overlaywidth }: width of the overlay
+%D \item \type{\overlayheight}: height plus depth of the overlay
+%D \item \type{\overlaydepth }: depth of the overlay
+%D \stopitemize
+%D
+%D The resulting box is lowered to the right depth.
+
+%def\overlaywidth {\the\hsize\space} % We preset the variables
+%def\overlayheight {\the\vsize\space} % to some reasonable default
+%def\overlaydepth {0pt } % values. The attributes
+%let\overlayoffset \overlaydepth % of the frame can be (are)
+%let\overlaylinewidth \overlaydepth % set somewhere else.
+\let\overlaycolor \empty
+\let\overlaylinecolor \empty
+
+\def\overlayradius{\framedparameter\c!frameradius}
+
+\newdimen\d_overlay_width
+\newdimen\d_overlay_height
+\newdimen\d_overlay_depth
+\newdimen\d_overlay_offset
+\newdimen\d_overlay_linewidth
+
+\let\m_overlay_region\empty
+
+% expandable ... in a future version the space will go (in my one can use Overlay*)
+
+\def\overlaywidth {\the\d_overlay_width \space} % We preset the variables
+\def\overlayheight {\the\d_overlay_height \space} % to some reasonable default
+\def\overlaydepth {\the\d_overlay_depth \space} % values.
+\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are)
+\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else.
+\def\overlayregion {\m_overlay_region}
+
+% public but kind of protected
+
+\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax}
+\def\usedoverlayheight {\dimexpr\d_overlay_height \relax}
+\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax}
+\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax}
+\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax}
+
+%D The next register is used to initialize overlays.
+
+\newtoks\everyoverlay
+
+%D An example of an initialization is the following (overlays can contain text
+%D and be executed under an regime where interlineskip is off).
+
+\installcorenamespace{overlay}
+\installcorenamespace{overlaybuiltin}
+
+\appendtoks
+ \oninterlineskip
+\to \everyoverlay
+
+\prependtoks
+ \hsize\d_overlay_width
+ \vsize\d_overlay_height
+\to \everyoverlay
+
+\unexpanded\def\defineoverlay
+ {\dodoubleargument\pack_framed_define_overlay}
+
+\def\pack_framed_define_overlay[#1][#2]%
+ {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
+ \processcommalist[#1]\pack_framed_define_overlay_indeed}
+
+\unexpanded\def\executedefinedoverlay#1#2% we can share the definitions
+ {\bgroup % redundant grouping
+ \setbox\scratchbox\hbox\bgroup
+ \ifzeropt\d_framed_target_dp
+ \the\everyoverlay#2% saves wrapping (and lua call)
+ \else
+ \lower\d_framed_target_dp
+ \hbox{\the\everyoverlay#2}%
+ \fi
+ \egroup
+ \setlayoutcomponentattribute{\v!overlay:#1}%
+ \setbox\scratchbox\hpack \layoutcomponentboxattribute
+ {\kern -.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width
+ \raise-.5\dimexpr\ht\scratchbox-\d_framed_target_ht\relax % not \d_overlay_height !
+ \box\scratchbox}%
+ \wd\scratchbox\d_framed_target_wd
+ \ht\scratchbox\d_framed_target_ht
+ \dp\scratchbox\d_framed_target_dp
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {overlayfakebox}
+
+% \unexpanded\def\overlayfakebox
+% {\hpack
+% {\setbox\scratchbox\emptyhbox
+% \wd\scratchbox\d_overlay_width
+% \ht\scratchbox\d_overlay_height
+% \box\scratchbox}}
+
+\unexpanded\def\overlayfakebox
+ {\hpack % redundant but needs testing
+ {\novrule
+ \s!width \d_overlay_width
+ \s!height\d_overlay_height
+ \s!depth \zeropoint}}
+
+%D For testing we provide:
+
+\def\doifelseoverlay#1% only tests external overlays
+ {\ifcsname\??overlay#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifoverlayelse\doifelseoverlay
+
+%D The content of the box will be (temporary) saved in a box. We also have an
+%D extra box for backgrounds.
+
+\newbox\b_framed_normal
+\newbox\b_framed_extra
+
+\newtoks\everybackgroundbox
+
+\let\m_framed_background\empty % we might need a public name
+
+\def\pack_framed_process_background
+ {\ifcsname\??overlaybuiltin\m_framed_background\endcsname
+ \expandafter\pack_framed_process_background_indeed_internal\lastnamedcs
+ \orelse\ifcsname\??overlay\m_framed_background\endcsname
+ \expandafter\pack_framed_process_background_indeed_external\lastnamedcs
+ \fi}
+
+\def\pack_framed_process_background_indeed_internal#1% % : in name
+ {\bgroup
+ \setbox\b_framed_extra\hpack\bgroup
+ \ifzeropt\framedbackgroundoffset\else
+ \kern-\framedbackgroundoffset
+ \fi
+ \hbox\bgroup#1\egroup
+ \egroup
+ \wd\b_framed_extra\zeropoint
+ \ht\b_framed_extra\framedbackgroundheight
+ \dp\b_framed_extra\framedbackgrounddepth
+ \box\b_framed_extra
+ \egroup}
+
+\def\pack_framed_process_background_indeed_external
+ {\pack_framed_overlay_initialize
+ \pack_framed_process_background_indeed_internal}
+
+\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground)
+ {\edef\m_framed_background{#1}%
+ \ifx\m_framed_background\s!unknown\else
+ \pack_framed_process_background
+ \expandafter\pack_framed_process_backgrounds
+ \fi#2}
+
+%D Beware, a backgroundbox can be empty which is another reason why we set the
+%D width to zero instead of back-skipping.
+
+\newdimen\framedbackgroundwidth
+\newdimen\framedbackgroundheight
+\newdimen\framedbackgrounddepth
+\newdimen\framedbackgroundoffset
+
+\def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise
+ {\vpack to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight
+
+\def\pack_framed_set_region % experiment
+ {\ifx\m_overlay_region\v!yes
+ \edef\m_overlay_region{\reservedautoregiontag}%
+ \fi}
+
+\def\pack_framed_add_region % experiment
+ {\anch_mark_tagged_box\b_framed_normal\m_overlay_region}
+
+\def\pack_framed_add_background
+ {\setbox\b_framed_normal\hpack % was vbox % see also *1*
+ {%\pack_framed_forgetall % can be relaxed
+ \boxmaxdepth\maxdimen
+ \framedbackgroundoffset\d_framed_backgroundoffset
+ \framedbackgroundwidth \wd\b_framed_normal
+ \framedbackgroundheight\ht\b_framed_normal
+ \framedbackgrounddepth \dp\b_framed_normal
+ \d_framed_target_wd\dimexpr\framedbackgroundwidth +2\framedbackgroundoffset\relax
+ \d_framed_target_ht\dimexpr\framedbackgroundheight+ \framedbackgroundoffset\relax
+ \d_framed_target_dp\dimexpr\framedbackgrounddepth + \framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax
+ \let\pack_framed_overlay_initialize\pack_framed_overlay_initialize_indeed
+ \ifx\p_framed_component\empty
+ \resetlayoutcomponentattribute
+ \else
+ \setlayoutcomponentattribute{\v!background:\p_framed_component}%
+ \fi
+ \let\foregroundbox\pack_framed_background_box_content
+ \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay
+ \the\everybackgroundbox % moved
+ \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it
+ \box\b_framed_normal
+ \hss
+ \egroup}}
+
+\def\pack_framed_overlay_initialize_indeed
+ {\d_overlay_width \d_framed_target_wd
+ \d_overlay_height \dimexpr\d_framed_target_ht+\d_framed_target_dp\relax
+ \d_overlay_depth \d_framed_target_dp
+ \d_overlay_linewidth \d_framed_linewidth
+ \d_overlay_offset \framedbackgroundoffset\relax
+ \edef\overlaycolor {\framedparameter\c!backgroundcolor}% let ?
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers
+ %\edef\overlaycorner {\framedparameter\c!backgroundcorner}%
+ %\edef\overlayradius {\framedparameter\c!backgroundradius}%
+ \let\pack_framed_overlay_initialize\relax}
+
+%D One can explictly insert the foreground box. For that purpose we introduce the
+%D overlay \type {foreground}.
+%D
+%D We predefine two already familiar backgrounds:
+
+%letvalue{\??overlaybuiltin\v!screen }\pack_framed_background_box_gray
+\letvalue{\??overlaybuiltin\v!color }\pack_framed_background_box_color
+\letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox]
+
+%D We can specify overlays as a comma separated list of overlays, a sometimes
+%D handy feature.
+%D
+%D Besides backgrounds (overlays) we also need some macros to draw outlines (ruled
+%D borders). Again we have to deal with square and round corners. The first category
+%D can be handled by \TEX\ itself, the latter one depends on the driver. This macro
+%D also support a negative offset.
+
+\def\pack_framed_add_outline
+ {\setbox\b_framed_normal\hpack % rules on top of box
+ {\d_framed_target_wd\dimexpr\wd\b_framed_normal+2\d_framed_frameoffset\relax
+ \d_framed_target_ht\dimexpr\ht\b_framed_normal+ \d_framed_frameoffset\relax
+ \d_framed_target_dp\dimexpr\dp\b_framed_normal+ \d_framed_frameoffset+\framedparameter\c!framedepth\relax
+ \ifdim\d_framed_target_dp<\zeropoint
+ \advance\d_framed_target_ht \d_framed_target_dp
+ \scratchdimen-\d_framed_target_dp
+ \d_framed_target_dp\zeropoint
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background
+ \setbox\b_framed_extra\hpack
+ {\kern-\d_framed_frameoffset
+ \raise\scratchdimen
+ \hpack{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}%
+ \wd\b_framed_extra\wd\b_framed_normal
+ \ht\b_framed_extra\ht\b_framed_normal
+ \dp\b_framed_extra\dp\b_framed_normal
+ \wd\b_framed_normal\zeropoint
+ \box\b_framed_normal
+ \box\b_framed_extra}}
+
+\def\pack_framed_stroked_box_normal_opened
+ {\setbox\scratchbox\vpack \bgroup
+ \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname
+ \nointerlineskip % new (needed for fences)
+ \hpack \bgroup
+ \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname
+ \novrule
+ \s!width \d_framed_target_wd
+ \s!height\d_framed_target_ht
+ \s!depth \d_framed_target_dp
+ \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname
+ \egroup
+ \nointerlineskip % new (needed for fences)
+ \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname
+ \egroup
+ \wd\scratchbox\d_framed_target_wd
+ \ht\scratchbox\d_framed_target_ht
+ \dp\scratchbox\d_framed_target_dp
+ \box\scratchbox}
+
+\def\pack_framed_stroked_box_normal_closed
+ {\hpack\bgroup
+ \scratchdimen.5\d_framed_linewidth
+ \hskip\scratchdimen
+ \clf_framedoutline
+ \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax
+ \dimexpr\d_framed_target_ht-\scratchdimen\relax
+ \dimexpr\d_framed_target_dp-\scratchdimen\relax
+ \d_framed_linewidth
+ \relax
+ \egroup}
+
+\def\pack_framed_stroked_box_normal
+ {\ifx\p_framed_frame\v!closed
+ \pack_framed_stroked_box_normal_closed
+ \else
+ \pack_framed_stroked_box_normal_opened
+ \fi}
+
+\def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth}
+\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth}
+\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth}
+\def\pack_framed_l_rule{\vrule\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
+
+\letvalue{\??framedtop \v!on \v!on}\pack_framed_t_rule
+\letvalue{\??framedtop \v!off\v!on}\pack_framed_t_rule
+\letvalue{\??framedtop \v!on }\pack_framed_t_rule
+
+\letvalue{\??framedbottom\v!on \v!on}\pack_framed_b_rule
+\letvalue{\??framedbottom\v!off\v!on}\pack_framed_b_rule
+\letvalue{\??framedbottom\v!on }\pack_framed_b_rule
+
+\letvalue{\??framedleft \v!on \v!on}\pack_framed_l_rule
+\letvalue{\??framedleft \v!off\v!on}\pack_framed_l_rule
+\letvalue{\??framedleft \v!on }\pack_framed_l_rule
+
+\letvalue{\??framedright \v!on \v!on}\pack_framed_r_rule
+\letvalue{\??framedright \v!off\v!on}\pack_framed_r_rule
+\letvalue{\??framedright \v!on }\pack_framed_r_rule
+
+% no overlapping rules
+
+\def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth}
+\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}}
+\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth}
+\def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
+
+\letvalue{\??framedtop \v!small\v!small}\pack_framed_t_rules
+\letvalue{\??framedtop \v!off \v!small}\pack_framed_t_rules
+\letvalue{\??framedtop \v!small }\pack_framed_t_rules
+
+\letvalue{\??framedbottom\v!small\v!small}\pack_framed_b_rules
+\letvalue{\??framedbottom\v!off \v!small}\pack_framed_b_rules
+\letvalue{\??framedbottom\v!small }\pack_framed_b_rules
+
+\letvalue{\??framedleft \v!small\v!small}\pack_framed_l_rules
+\letvalue{\??framedleft \v!off \v!small}\pack_framed_l_rules
+\letvalue{\??framedleft \v!small }\pack_framed_l_rules
+
+\letvalue{\??framedright \v!small\v!small}\pack_framed_r_rules
+\letvalue{\??framedright \v!off \v!small}\pack_framed_r_rules
+\letvalue{\??framedright \v!small }\pack_framed_r_rules
+
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=on,leftframe=on,topframe=on,bottomframe=on]
+% {}
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=small]
+% {}
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on]
+% {}
+
+%D The next few macros are probably the most misused ones in \CONTEXT. They deal
+%D with putting rules around boxes, provide backgrounds, offer alignment features,
+%D and some more. We start with defining some booleans. These give an impression of
+%D what we are going to take into account.
+
+% todo : \c_framed_hasoffset
+% faster : \let\c_framed_hasoffset\falseconditional
+
+\newconditional\c_framed_has_offset
+\newconditional\c_framed_has_width
+\newconditional\c_framed_has_height
+\newconditional\c_framed_has_format
+\newconditional\c_framed_is_overlaid
+\newconditional\c_framed_has_frame
+\newconditional\c_framed_has_extra_offset
+\newconditional\c_framed_text_location_none
+
+\newconstant \c_framed_has_strut % 0=relaxes 1=pseudostruts 2=realstruts
+
+%D \macros
+%D {framed, setupframed}
+%D
+%D Ruled boxes are typeset using \type{\framed}. This command is quite versatile
+%D and, although some users will probably seldom use it, one cannot overlook its
+%D features.
+%D
+%D \showsetup{setupframed}
+%D \showsetup{framed}
+%D
+%D This general macro is a special version of an even more general case, that can
+%D easily be linked into other macros that need some kind of framing. The local
+%D version is called with an extra parameter: the variable identifier. The reason
+%D for passing this identifier between brackets lays in the mere fact that this way
+%D we can use the optional argument grabbers.
+
+\def\defaultframeoffset{.25\exheight}
+
+\installcorenamespace{regularframedlevel}
+
+\unexpanded\def\installregularframed#1%
+ {\defineframed[#1]}
+
+\unexpanded\def\presetlocalframed[#1]%
+ {\defineframed[#1]}
+
+% \presetlocalframed[\??framed]
+
+\newcount\c_pack_framed_nesting
+
+\unexpanded\def\pack_framed_process_framed[#1]%
+ {\bgroup
+ \iffirstargument % faster
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed}
+
+\unexpanded\def\framed
+ {\bgroup
+ \advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \dosingleempty\pack_framed_process_framed}
+
+\unexpanded\def\startframed
+ {\dosingleempty\pack_framed_start_framed}
+
+\def\pack_framed_start_framed[#1]%
+ {\bgroup
+ \doifelseassignment{#1}\pack_framed_start_framed_yes\pack_framed_start_framed_nop{#1}}
+
+\def\pack_framed_start_framed_yes#1%
+ {\advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \iffirstargument\secondargumenttrue\fi % dirty trick
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \bgroup
+ \iffirstargument
+ \secondargumenttrue % dirty trick
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed
+ \bgroup
+ \ignorespaces}
+
+\def\pack_framed_start_framed_nop#1%
+ {\edef\currentframed{#1}%
+ \dosingleempty\pack_framed_start_framed_nop_indeed}
+
+\def\pack_framed_start_framed_nop_indeed[#1]%
+ {\pack_framed_initialize
+ \bgroup
+ \iffirstargument
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed
+ \bgroup
+ \ignorespaces}
+
+% till here
+
+\unexpanded\def\stopframed
+ {\removeunwantedspaces
+ \egroup}
+
+\unexpanded\def\normalframedwithsettings[#1]%
+ {\bgroup
+ \advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \bgroup
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \setupcurrentframed[#1]%
+ \pack_framed_process_indeed}
+
+%D \startbuffer
+%D \setupframed [framecolor=yellow] \framed{A}
+%D \defineframed[myframed] [framecolor=blue] \myframed{B}
+%D \setupframed [myframed] [framecolor=red] \myframed{C}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \presetlocalframed[myframed]
+%D \localframed[myframed][framecolor=green]{oeps}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {ifinframed}
+%D
+%D The normal case first presets all parameters and next starts looking for the user
+%D supplied ones. The first step is omitted in the local case, because these are
+%D preset at declaration time and keep their values unless explictly changed. By
+%D presetting the variables everytime the normal command is called, we can use this
+%D command nested, without the unwanted side effect of inheritance. The boolean is
+%D used to speed up the color stack.
+
+\newif\ifinframed
+
+%D The next one is faster on multiple backgrounds per page. No
+%D dimensions can be set, only frames and backgrounds.
+
+\unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4
+ {\bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \setbox\b_framed_normal\hbox{#4}%
+ \iftrialtypesetting \else
+ \edef\m_overlay_region{\framedparameter\c!region}%
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_set_region
+ \fi
+ \fi
+ \setupcurrentframed[#3]%
+ \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
+ \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds
+ \edef\p_framed_frame{\framedparameter\c!frame}%
+ \edef\p_framed_background{\framedparameter\c!background}%
+ % not here, in calling macro: setups
+ \pack_framed_remove_depth
+ \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
+ \ifx\p_framed_rulethickness\empty\else
+ \d_framed_linewidth\p_framed_rulethickness\relax
+ \fi
+ \pack_framed_add_outline % real or invisible frame
+ \fi\fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ \edef\p_framed_component{\framedparameter\c!component}%
+ \pack_framed_add_background
+ \fi
+ \pack_framed_restore_depth
+ \iftrialtypesetting \else
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_add_region
+ \fi
+ \fi
+ \box\b_framed_normal
+ \egroup}
+
+%D The next macro uses a box and takes its natural width and height so these
+%D can better be correct.
+
+\unexpanded\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage)
+ {\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2
+ \edef\m_overlay_region{\framedparameter\c!region}%
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_set_region
+ \fi
+ \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
+ \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds
+ \edef\p_framed_frame{\framedparameter\c!frame}%
+ \edef\p_framed_background{\framedparameter\c!background}%
+ \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
+ \ifx\p_framed_rulethickness\empty \else
+ \d_framed_linewidth\p_framed_rulethickness\relax
+ \fi
+ \pack_framed_add_outline % real or invisible frame
+ \fi\fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ \edef\p_framed_component{#1}%
+ \pack_framed_add_background
+ \fi
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_add_region
+ \fi
+ \box\b_framed_normal
+ \egroup}
+
+\unexpanded\def\localbackgroundframed#1% namespace component box
+ {\bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \pack_framed_process_box_indeed} % group ends here
+
+\let\postprocessframebox\relax
+
+%D A nice example by Aditya:
+%D
+%D \starttyping
+%D \setupframed
+%D [loffset=\framedparameter{hoffset},
+%D roffset=\framedparameter{hoffset},
+%D hoffset=\zeropoint]
+%D
+%D \defineframed[test][hoffset=1cm]
+%D \stoptyping
+
+\newdimen\d_framed_width
+\newdimen\d_framed_height
+\newdimen\d_framed_frameoffset
+\newdimen\d_framed_backgroundoffset
+\newdimen\d_framed_local_offset
+
+% todo: protect local \framednames
+
+\unexpanded\def\localframed
+ {\bgroup
+ \dodoubleempty\pack_framed_local}
+
+\unexpanded\def\pack_framed_local[#1][#2]%
+ {\bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \ifsecondargument % faster
+ \setupcurrentframed[#2]% here !
+ \fi
+ \pack_framed_process_indeed}
+
+\unexpanded\def\directlocalframed[#1]% no optional
+ {\bgroup
+ \bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \pack_framed_process_indeed}
+
+\unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between)
+ {\bgroup
+ \bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \setupcurrentframed[#2]% here !
+ \pack_framed_process_indeed}
+
+% done
+
+\def\c!fr!analyze{fr:analyze} % private option
+
+\let\delayedbegstrut\relax
+\let\delayedendstrut\relax
+\let\delayedstrut \relax
+
+\let\localoffset\empty
+\let\localwidth \empty
+\let\localheight\empty
+\let\localformat\empty
+\let\localstrut \empty
+
+\unexpanded\def\pack_framed_process_indeed
+ {\d_framed_frameoffset\framedparameter\c!frameoffset
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ % new, experimental dirty hook
+ \framedparameter\c!extras
+ % to get the right spacing
+ \edef\p_framed_foregroundstyle{\framedparameter\c!foregroundstyle}%
+ \ifx\p_framed_foregroundstyle\empty\else\dousestyleparameter\p_framed_foregroundstyle\fi
+ % beware, both the frame and background offset can be overruled
+ %
+ \edef\p_framed_setups{\framedparameter\c!setups}%
+ % the next macros are visible
+ \edef\localoffset{\framedparameter\c!offset}%
+ \edef\localwidth {\framedparameter\c!width}%
+ \edef\localheight{\framedparameter\c!height}%
+ \edef\localformat{\framedparameter\c!align}%
+ \edef\localstrut {\framedparameter\c!strut}%
+ % these are not
+ \edef\p_framed_autostrut {\framedparameter\c!autostrut}%
+ \edef\p_framed_frame {\framedparameter\c!frame}%
+ \edef\p_framed_location {\framedparameter\c!location}%
+ \edef\p_framed_orientation{\framedparameter\c!orientation}%
+ \edef\p_framed_anchoring {\framedparameter\c!anchoring}%
+ %
+ \edef\p_framed_autowidth {\framedparameter\c!autowidth}%
+ \edef\p_framed_franalyze {\framedparameter\c!fr!analyze}% experimental option
+ %
+ \ifx\p_framed_frame\v!overlay % no frame, no offset, no framewidth
+ \setfalse\c_framed_has_frame
+ \let\localoffset\v!overlay
+ \orelse\ifx\p_framed_frame\v!none % no frame, no framewidth
+ \setfalse\c_framed_has_frame
+ \else
+ \settrue\c_framed_has_frame
+ \fi
+ \ifconditional\c_framed_has_frame
+ \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}%
+ \ifx\p_framed_rulethickness\empty\else
+ \d_framed_linewidth\p_framed_rulethickness\relax
+ \fi
+ \else
+ \d_framed_linewidth\zeropoint
+ \fi
+ % 2013/03/12: a change of order (sizes before align
+ \ifx\localwidth\v!local
+ \setlocalhsize
+ \fi
+ %
+ \forgetall % should happen after \localwidth but before align
+ %
+ \ifx\localformat\empty
+ \setfalse\c_framed_has_format
+ \else
+ \settrue\c_framed_has_format
+ \dosetraggedcommand\localformat % not that fast
+ \fi
+ %
+ \ifcsname\??framedoffsetalternative\localoffset\endcsname
+ \lastnamedcs
+ \else
+ \framed_offset_alternative_unknown
+ \fi
+ \ifcsname\??framedwidthalternative\localwidth\endcsname
+ \lastnamedcs
+ \else
+ \framed_width_alternative_unknown
+ \fi
+ \ifcsname\??framedheightalternative\localheight\endcsname
+ \lastnamedcs
+ \else
+ \framed_height_alternative_unknown
+ \fi
+ % the next check could move to heightalternative
+ \ifconditional\c_framed_has_height
+ % obey user set height, also downward compatible
+ \else
+ \edef\p_framed_lines{\framedparameter\c!lines}%
+ \ifx\p_framed_lines\empty\else
+ \ifcase\p_framed_lines\else
+ \d_framed_height\p_framed_lines\lineheight
+ \edef\localheight{\the\d_framed_height}%
+ \settrue\c_framed_has_height
+ \fi
+ \fi
+ \fi
+ % this is now an option: width=local
+ %
+ % \ifdim\d_framed_width=\hsize
+ % \parindent\zeropoint
+ % \setlocalhsize
+ % \d_framed_width\localhsize
+ % \fi
+ % i.e. disable (colsetbackgroundproblemintechniek)
+ \advance\d_framed_width -2\d_framed_local_offset
+ \advance\d_framed_height -2\d_framed_local_offset
+ \ifcsname\??framedstrutalternative\localstrut\endcsname
+ \lastnamedcs
+ \else
+ \framed_offset_alternative_unknown
+ \fi
+ % the next check could move to strutalternative
+ \ifcase\c_framed_has_strut % none (not even noindent)
+ \let\localbegstrut\relax
+ \let\localendstrut\relax
+ \let\localstrut \relax
+ \or % no / overlay
+ \let\localbegstrut\pseudobegstrut
+ \let\localendstrut\pseudoendstrut
+ \let\localstrut \pseudostrut
+ \else
+ \let\localbegstrut\begstrut
+ \let\localendstrut\endstrut
+ \let\localstrut \strut
+ \fi
+ \ifx\p_framed_autostrut\v!yes
+ \let\delayedbegstrut\relax
+ \let\delayedendstrut\relax
+ \let\delayedstrut \relax
+ \else
+ \let\delayedbegstrut\localbegstrut
+ \let\delayedendstrut\localendstrut
+ \let\delayedstrut \localstrut
+ \let\localbegstrut \relax
+ \let\localendstrut \relax
+ \let\localstrut \relax
+ \fi
+ \ifconditional\c_framed_has_height
+ \let\\\pack_framed_vboxed_newline
+ \ifconditional\c_framed_has_width
+ \let\hairline\pack_framed_vboxed_hairline
+ \ifconditional\c_framed_has_format
+ \let\next\pack_framed_format_format_yes
+ \else
+ \let\next\pack_framed_format_format_nop
+ \fi
+ \else
+ \let\hairline\pack_framed_hboxed_hairline
+ \ifconditional\c_framed_has_format
+ \let\next\pack_framed_format_format_height
+ \else
+ \let\next\pack_framed_format_format_vsize
+ \fi
+ \fi
+ \orelse\ifconditional\c_framed_has_width
+ \ifconditional\c_framed_has_format
+ \let\hairline\pack_framed_vboxed_hairline
+ \let\\\pack_framed_vboxed_newline
+ \let\next\pack_framed_format_format_width
+ \else
+ \let\hairline\pack_framed_hboxed_hairline
+ \let\\\pack_framed_hboxed_newline
+ \let\next\pack_framed_format_format_hsize
+ \fi
+ \else
+ \let\hairline\pack_framed_hboxed_hairline
+ \let\\\pack_framed_hboxed_newline
+ \let\next\pack_framed_format_format_no_size
+ \fi
+ \pack_framed_check_extra_offsets
+ \edef\p_framed_background{\framedparameter\c!background}%
+% \ifx\p_framed_background\empty
+% \let\pack_framed_forgetall\forgetall
+% \else
+% \let\pack_framed_forgetall\relax
+% \forgetall
+% \fi
+ \edef\framedwidth {\the\ifdim\d_framed_width >\zeropoint \d_framed_width \else\zeropoint\fi}% public
+ \edef\framedheight{\the\ifdim\d_framed_height>\zeropoint \d_framed_height\else\zeropoint\fi}% public
+ \edef\framedoffset{\the\dimexpr\ifconditional\c_framed_has_offset\localoffset \else\zeropoint\fi}% public
+ \ifx\p_framed_orientation\empty
+ \let\pack_framed_stop_orientation\relax
+ \else
+ \pack_framed_start_orientation
+ \fi
+ \afterassignment\pack_framed_restart
+ \setbox\b_framed_normal\next}
+
+% alternatives for width, height, strut and offset
+
+\installcorenamespace{framedwidthalternative}
+\installcorenamespace{framedheightalternative}
+\installcorenamespace{framedstrutalternative}
+\installcorenamespace{framedoffsetalternative}
+
+% widths
+
+\setvalue{\??framedwidthalternative\empty}%
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!fit}%
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!fixed}% equals \v!fit but no shapebox
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!broad}%
+ {\settrue\c_framed_has_width
+ \d_framed_width\hsize}
+
+\setvalue{\??framedwidthalternative\v!max}% idem broad
+ {\settrue\c_framed_has_width
+ \d_framed_width\hsize}
+
+\setvalue{\??framedwidthalternative\v!local}%
+ {\settrue\c_framed_has_width
+ %\setlocalhsize
+ \d_framed_width\localhsize}
+
+\setvalue{\??framedwidthalternative\s!unknown}%
+ {\settrue\c_framed_has_width
+ \d_framed_width\localwidth}
+
+\def\framed_width_alternative_unknown
+ {\settrue\c_framed_has_width
+ \d_framed_width\localwidth}
+
+% heights
+
+\setvalue{\??framedheightalternative\empty}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!fit}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!broad}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!max}%
+ {\settrue\c_framed_has_height
+ \d_framed_height\vsize}
+
+\setvalue{\??framedheightalternative\s!unknown}%
+ {\settrue\c_framed_has_height
+ \d_framed_height\localheight}
+
+\def\framed_height_alternative_unknown
+ {\settrue\c_framed_has_height
+ \d_framed_height\localheight}
+
+% struts (use let instead?)
+
+\setvalue{\??framedstrutalternative\v!no}%
+ {\c_framed_has_strut\plusone}
+
+\setvalue{\??framedstrutalternative\v!global}%
+ {\setstrut}
+
+\setvalue{\??framedstrutalternative\v!local}%
+ {\setfontstrut}
+
+\setvalue{\??framedstrutalternative\v!yes}%
+ {\setstrut}
+
+\setvalue{\??framedstrutalternative\s!unknown}%
+ {\setstrut}
+
+\def\framed_strut_alternative_unknown
+ {\setstrut}
+
+\setvalue{\??framedstrutalternative\v!none}% not even pseudo struts
+ {\c_framed_has_strut\zerocount}
+
+% offsets
+
+\setvalue{\??framedoffsetalternative\v!none}%
+ {\setfalse\c_framed_has_offset
+ \c_framed_has_strut\plusone
+ \setfalse\c_framed_is_overlaid
+ \d_framed_local_offset\d_framed_linewidth}
+
+\setvalue{\??framedoffsetalternative\v!overlay}%
+ {% \ifx\p_framed_frame\v!no \setfalse\c_framed_has_frame \fi % test first
+ \setfalse\c_framed_has_offset
+ \c_framed_has_strut\plusone
+ \settrue\c_framed_is_overlaid
+ \d_framed_local_offset\zeropoint}
+
+% \setvalue{\??framedoffsetalternative\v!strut}%
+% {\setfalse\c_framed_has_offset
+% \c_framed_has_strut\plustwo
+% \settrue\c_framed_is_overlaid
+% \d_framed_local_offset\zeropoint}
+
+\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000
+ {\settrue \c_framed_has_offset
+ \c_framed_has_strut\plustwo
+ \setfalse\c_framed_is_overlaid
+ \let\localoffset\defaultframeoffset
+ \letframedparameter\c!offset\defaultframeoffset % brrr
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
+\def\framed_offset_alternative_unknown
+ {\settrue \c_framed_has_offset
+ \c_framed_has_strut\plustwo
+ \setfalse\c_framed_is_overlaid
+ \let\defaultframeoffset\localoffset
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
+\letvalue{\??framedoffsetalternative\s!unknown}\framed_offset_alternative_unknown
+
+% so far for alternatives
+
+\let\pack_framed_stop_orientation\relax
+
+\def\pack_framed_restart
+ {\aftergroup\pack_framed_finish}
+
+\def\pack_framed_do_top
+ {\raggedtopcommand
+ \framedparameter\c!top
+ \edef\p_blank{\framedparameter\c!blank}%
+ \ifx\p_blank\v!yes\else % auto or no
+ \doinhibitblank
+ \fi}
+
+\def\pack_framed_do_bottom
+ {\framedparameter\c!bottom
+ \raggedbottomcommand}
+
+%D Careful analysis of this macro will learn us that not all branches in the last
+%D conditionals can be encountered, that is, some assignments to \type{\next} will
+%D never occur. Nevertheless we implement the whole scheme, if not for future
+%D extensions.
+
+%D \macros
+%D {doassigncheckedframeoffset}
+%D
+%D Offset helper (see menus):
+
+\def\doassigncheckedframeoffset#1#2% could be a fast \csname .. \endcsname
+ {\edef\checkedframeoffset{#2}%
+ #1%
+ \ifx\checkedframeoffset\empty \zeropoint\orelse
+ \ifx\checkedframeoffset\v!overlay\zeropoint\orelse
+ \ifx\checkedframeoffset\v!none \zeropoint\orelse
+ \ifx\checkedframeoffset\v!frame \zeropoint\orelse
+ \ifx\checkedframeoffset\v!default\zeropoint\else
+ #2%
+ \fi
+ \relax}
+
+%D \macros
+%D {ifreshapeframebox}
+%D
+%D The last few lines tell what to do after the content of the box is collected and
+%D passed to the next macro. In the case of a fixed width and centered alignment,
+%D the content is evaluated and used to determine the most natural width. The rest
+%D of the code deals with backgrounds and frames.
+
+\newif\ifreshapeframebox \reshapeframeboxtrue
+
+%D Beware: setting \type {top} and \type {bottom} to nothing, may
+%D result in a frame that is larger that the given height! try:
+%D
+%D \starttyping
+%D \framed
+%D [height=3cm,top=,bottom=,offset=overlay]
+%D {\strut test \shapefill \strut test}
+%D \stoptyping
+%D
+%D This is intended behaviour and not a bug! One can always set
+%D
+%D \starttyping
+%D ...,bottom=\kern0pt,...
+%D \stoptyping
+
+% experiment ... \p_framed_franalyze -> we could support 'first' as location key
+% option but then we will always do an analysis and reimplement the location
+% options (btw, beware of location settings of derived functionality that bleed
+% into this
+
+\def\pack_framed_finish_a
+ {\ifreshapeframebox
+ \pack_framed_reshape_process
+ \orelse\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
+ \else
+ \pack_framed_reshape_reset
+ \fi
+ \setfalse\c_framed_has_width}
+
+\def\pack_framed_finish_b
+ {\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
+ \else
+ \pack_framed_reshape_reset
+ \fi
+ \setfalse\c_framed_has_width}
+
+\def\pack_framed_finish_c
+ {\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
+ \else
+ \pack_framed_reshape_reset
+ \fi}
+
+\def\pack_framed_profile_box
+ {\profilegivenbox\p_profile\b_framed_normal
+ \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}}
+
+\unexpanded\def\pack_framed_finish
+ {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down
+ \pack_framed_locator_before\p_framed_location
+ \ifconditional\c_framed_has_format
+ %\ifconditional\c_framed_has_height \else
+ % \edef\p_profile{\framedparameter\c!profile}%
+ % \ifx\p_profile\empty\else
+ % \pack_framed_profile_box
+ % \fi
+ %\fi
+ \ifx\p_framed_autowidth\v!force
+ \pack_framed_finish_a
+ \orelse\ifx\localwidth\v!fit
+ \ifx\p_framed_autowidth\v!yes
+ \pack_framed_finish_a
+ \else
+ \pack_framed_finish_b
+ \fi
+ \orelse\ifx\localwidth\v!fixed
+ \pack_framed_finish_b
+ \else
+ \pack_framed_finish_c
+ \fi
+ \ifconditional\c_framed_has_height \else
+ \edef\p_profile{\framedparameter\c!profile}%
+ \ifx\p_profile\empty\else
+ \pack_framed_profile_box
+ \fi
+ \fi
+ \ifconditional\page_postprocessors_needed_box
+ % quite late
+ \page_postprocessors_linenumbers_box\b_framed_normal
+ \fi
+ \else
+ \pack_framed_finish_c
+ \fi
+ \ifconditional\c_framed_has_width
+ \wd\b_framed_normal\d_framed_width
+ \fi
+ \ifconditional\c_framed_has_height
+ \ht\b_framed_normal\d_framed_height
+ \else
+ \edef\p_framed_minheight{\framedparameter\c!minheight}%
+ \ifx\p_framed_minheight\empty \else
+ \ifdim\ht\b_framed_normal<\p_framed_minheight
+ \ht\b_framed_normal\p_framed_minheight
+ \fi
+ \fi
+ \fi
+ \edef\p_framed_empty{\framedparameter\c!empty}%
+ \ifx\p_framed_empty\v!yes
+ \pack_framed_fake_box
+ \fi
+ \ifx\p_framed_anchoring\empty\else
+ \pack_framed_handle_anchoring
+ \fi
+ \pack_framed_stop_orientation % moved here at 2014-05-25
+ \iftrialtypesetting \else
+ \edef\m_overlay_region{\framedparameter\c!region}%
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_set_region
+ \fi
+ \fi
+ \d_framed_applied_offset
+ \ifconditional\c_framed_is_overlaid
+ \zeropoint
+ \else
+ \d_framed_linewidth
+ \fi
+ \ifconditional\c_framed_has_offset
+ \advance\d_framed_applied_offset\localoffset
+ \fi
+ \ifconditional\c_framed_has_extra_offset
+ \pack_framed_apply_extra_offsets % includes \d_framed_applied_offset
+ \else
+ \ifzeropt\d_framed_applied_offset
+ \else
+ \pack_framed_widen_box
+ \fi
+ \fi
+ %
+ \ifx\postprocessframebox\relax \else
+ \let\next\postprocessframebox
+ \let\postprocessframebox\relax % prevent nesting
+ \next\b_framed_normal
+ \fi
+ \iftrialtypesetting
+ % new
+ \else
+ \ifconditional\c_framed_has_frame % real or invisible frame
+ \pack_framed_add_outline
+ \fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_component{\framedparameter\c!component}%
+ \pack_framed_add_background
+ \fi
+ \fi
+ \pack_framed_locator_after\p_framed_location
+ \iftrialtypesetting \else
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_add_region
+ \fi
+ \fi
+ \box\b_framed_normal
+ \global\frameddimensionstate % global so to be used directly afterwards !
+ \ifconditional\c_framed_has_width
+ \ifconditional\c_framed_has_height \plusthree \else \plusone \fi
+ \else
+ \ifconditional\c_framed_has_height \plustwo \else \zerocount \fi
+ \fi
+ \egroup
+ \egroup}
+
+%D Anchoring is experimental and was prototyped around the ctx meeting in 2018 but
+%D never mede it into the core yet. It operates indepedent of the orientation
+%D mechanism already present.
+
+\let\pack_framed_handle_anchoring\relax
+
+\installcorenamespace{framedlocatorbefore}
+\installcorenamespace{framedlocatorafter}
+
+\newconstant\frameddimensionstate % global state: 0=unknown 1=width 2=height 3=both
+
+\def\pack_framed_fake_box
+ {\setbox\scratchbox\emptyhbox
+ \wd\scratchbox\wd\b_framed_normal
+ \ht\scratchbox\ht\b_framed_normal
+ \dp\scratchbox\dp\b_framed_normal
+ \setbox\b_framed_normal\box\scratchbox}
+
+\def\installframedlocator#1#2#3%
+ {\setvalue{\??framedlocatorbefore#1}{#2}%
+ \setvalue{\??framedlocatorafter #1}{#3}}
+
+\def\pack_framed_locator_before#1{\begincsname\??framedlocatorbefore#1\endcsname}
+\def\pack_framed_locator_after #1{\begincsname\??framedlocatorafter #1\endcsname}
+
+\newdimen\d_framed_locator_ht
+\newdimen\d_framed_locator_dp
+\newdimen\d_framed_locator_lo
+\newdimen\d_framed_locator_ro
+
+\def\pack_framed_locator_set#1%
+ {\d_framed_locator_ht\dimexpr
+ #1+\d_framed_linewidth
+ \ifconditional\c_framed_has_offset
+ +\framedparameter\c!offset
+ \fi
+ +\framedparameter\c!toffset
+ \relax
+ \d_framed_locator_dp\dimexpr\ht\b_framed_normal-\d_framed_locator_ht\relax}
+
+\def\pack_framed_locator_set_lo
+ {\global\d_framed_locator_lo\dimexpr
+ \d_framed_linewidth
+ \ifconditional\c_framed_has_offset
+ +\framedparameter\c!offset
+ \fi
+ +\framedparameter\c!loffset
+ \relax}
+
+\def\pack_framed_locator_set_ro
+ {\global\d_framed_locator_ro\dimexpr
+ \d_framed_linewidth
+ \ifconditional\c_framed_has_offset
+ +\framedparameter\c!offset
+ \fi
+ +\framedparameter\c!roffset
+ \relax}
+
+% \ruledhbox
+% {A
+% \framed[width=2cm,align=middle,location=hanging]{location\\equals\\hanging}
+% \framed[width=2cm,align=middle,location=depth] {location\\equals\\depth}
+% \framed[width=2cm,align=middle,location=height] {location\\equals\\height}
+% B}
+% \vskip2cm
+% \ruledhbox
+% {A
+% \framed[width=2cm,align=middle,location=low] {location\\equals\\low}
+% \framed[width=2cm,align=middle,location=line] {location\\equals\\line}
+% \framed[width=2cm,align=middle,location=high] {location\\equals\\high}
+% B}
+% \vskip2cm
+% \ruledhbox
+% {A
+% \framed[width=2cm,align=middle,location=top] {location\\equals\\top}
+% \framed[width=2cm,align=middle,location=bottom] {location\\equals\\bottom}
+% \framed[width=2cm,align=middle,location=lohi] {location\\equals\\lohi}
+% \framed[width=2cm,align=middle,location=middle] {location\\equals\\middle}
+% B}
+
+% \installframedlocator \v!hanging % best with strut=no
+% {}
+% {\dp\b_framed_normal\ht\b_framed_normal
+% \ht\b_framed_normal\zeropoint}
+%
+% \installframedlocator \v!depth
+% {}
+% {\ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
+% \dp\b_framed_normal\strutdp
+% \box\b_framed_normal}
+%
+% \installframedlocator \v!height
+% {}
+% {\dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
+% \ht\b_framed_normal\strutht
+% \box\b_framed_normal}
+
+\installframedlocator \v!hanging % best with strut=no *1* / see mail to list by SB
+ {}
+ {\scratchdimen\ht\b_framed_normal
+ \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
+ \dp\b_framed_normal\scratchdimen
+ \ht\b_framed_normal\zeropoint
+ \box\b_framed_normal}
+
+\installframedlocator \v!depth % *1*
+ {}
+ {\setbox\b_framed_normal\hpack{\lower\strutdp\box\b_framed_normal}%
+ \ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
+ \dp\b_framed_normal\strutdp
+ \box\b_framed_normal}
+
+\installframedlocator \v!height % *1*
+ {}
+ {\scratchdimen\dimexpr \ht\b_framed_normal - \strutht \relax
+ \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
+ \dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
+ \ht\b_framed_normal\strutht
+ \box\b_framed_normal}
+
+\installframedlocator \v!high
+ {}
+ {\pack_framed_locator_set\strutht
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
+ \ht\b_framed_normal\strutht
+ \dp\b_framed_normal\strutdp
+ \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing?
+
+\installframedlocator \v!line
+ {}
+ {\setbox\b_framed_normal\hpack{\lower.5\ht\b_framed_normal\box\b_framed_normal}%
+ \ht\b_framed_normal.5\lineheight
+ \dp\b_framed_normal.5\lineheight
+ \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing?
+
+\installframedlocator \v!low
+ {}
+ {\pack_framed_locator_set\strutdp
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
+ \ht\b_framed_normal\strutht
+ \dp\b_framed_normal\strutdp
+ \box\b_framed_normal}
+
+\installframedlocator \v!top
+ {}
+ {\pack_framed_locator_set\strutht
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
+ \ht\b_framed_normal\d_framed_locator_ht
+ \dp\b_framed_normal\d_framed_locator_dp
+ \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing?
+
+\installframedlocator \v!middle
+ {}
+ {\scratchdimen.5\ht\b_framed_normal
+ \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
+ \ht\b_framed_normal\scratchdimen
+ \dp\b_framed_normal\scratchdimen
+ \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing?
+
+\installframedlocator \v!lohi % maybe also \v!center
+ {\pack_framed_locator_before\v!middle}
+ {\pack_framed_locator_after \v!middle}
+
+\installframedlocator \v!bottom
+ {}
+ {\pack_framed_locator_set\strutdp
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
+ \ht\b_framed_normal\d_framed_locator_dp
+ \dp\b_framed_normal\d_framed_locator_ht
+ \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing?
+
+\installframedlocator \v!keep % retains height/depth
+ {\pack_framed_remove_depth}
+ {\pack_framed_restore_depth}
+
+\newdimen\d_framed_formula
+
+\installframedlocator \v!formula % private, will become a more generic name
+ {}
+ {\pack_framed_locator_set\d_framed_formula
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
+ \ht\b_framed_normal\d_framed_locator_ht
+ \dp\b_framed_normal\d_framed_locator_dp
+ \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing?
+
+% also used in fastlocalframed
+
+\newdimen\d_framed_original_wd
+\newdimen\d_framed_original_ht
+\newdimen\d_framed_original_dp
+
+\def\pack_framed_remove_depth
+ {\d_framed_original_wd\wd\b_framed_normal
+ \d_framed_original_ht\ht\b_framed_normal
+ \d_framed_original_dp\dp\b_framed_normal
+ \ifzeropt\d_framed_original_dp\else
+ \setbox\b_framed_normal\hpack{\raise\d_framed_original_dp\box\b_framed_normal}%
+ \fi
+ \wd\b_framed_normal\d_framed_original_wd
+ \ht\b_framed_normal\dimexpr\d_framed_original_ht+\d_framed_original_dp\relax
+ \dp\b_framed_normal\zeropoint}
+
+\def\pack_framed_restore_depth
+ {\ifzeropt\d_framed_original_dp \else
+ \setbox\b_framed_normal\hpack{\lower\d_framed_original_dp\box\b_framed_normal}%
+ \fi
+ \wd\b_framed_normal\d_framed_original_wd
+ \ht\b_framed_normal\d_framed_original_ht
+ \dp\b_framed_normal\d_framed_original_dp}
+
+% \framed[width=12cm,height=3cm,orientation=0]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=90]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=180]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=270]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=-90]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=-180]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=-270]{\input ward\relax}
+
+\def\pack_framed_start_orientation
+ {\ifcase\p_framed_orientation
+ \let\pack_framed_stop_orientation\relax
+ \else
+ \let\pack_framed_stop_orientation\pack_framed_stop_orientation_indeed
+ \fi}
+
+\def\pack_framed_stop_orientation_indeed
+ {\setbox\b_framed_normal\hpack{\dorotatebox\p_framed_orientation\hpack{\box\b_framed_normal}}%
+ \d_framed_height\ht\b_framed_normal
+ \d_framed_width \wd\b_framed_normal}
+
+%D The last conditional takes care of the special situation of in||line \inframed
+%D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the
+%D running text.
+
+\unexpanded\def\inframed
+ {\dosingleempty\pack_framed_inline}
+
+% \def\pack_framed_inline[#1]%
+% {\framed[\c!location=\v!low,#1]}
+%
+% or:
+
+\def\pack_framed_inline[%
+ {\framed[\c!location=\v!low,}
+
+%D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background,
+%D but no content, so actually we have a sort of phantom framed box.
+
+%D \macros
+%D {mframed, minframed}
+%D
+%D When Tobias asked how to frame mathematical elements in formulas, Taco's posted the
+%D next macro:
+%D
+%D \starttyping
+%D \def\mframed#1%
+%D {\relax
+%D \ifmmode
+%D \vcenter{\hbox{\framed{$\ifinner\else\displaystyle\fi#1$}}}%
+%D \else
+%D \framed{$#1$}%
+%D \fi}
+%D \stoptyping
+%D
+%D Because \type {\ifinner} does not (always) reports what one would expect, we move the
+%D test to the outer level. We also want to pass arguments,
+%D
+%D \starttyping
+%D \def\mframed%
+%D {\dosingleempty\domframed}
+%D
+%D \def\domframed[#1]#2% % tzt \dowithnextmathbox ?
+%D {\relax
+%D \ifmmode
+%D \ifinner
+%D \inframed[#1]{$#2$}%
+%D \else
+%D \vcenter{\hbox{\framed[#1]{$\displaystyle#2$}}}%
+%D \fi
+%D \else
+%D \inframed[#1]{$#2$}%
+%D \fi}
+%D \stoptyping
+%D
+%D Still better is the next alternative, if only because it takes care of setting the super-
+%D and subscripts styles
+
+\newcount\c_framed_mstyle
+
+\unexpanded\def\pack_framed_math_strut
+ {\Ustartmath
+ \triggermathstyle\c_framed_mstyle
+ \vphantom{(}%
+ \Ustopmath}
+
+\installcorenamespace{mathframed}
+
+\installframedcommandhandler \??mathframed {mathframed} \??mathframed
+
+\appendtoks
+ \setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}%
+\to \everydefinemathframed
+
+\unexpanded\def\pack_framed_mathframed#1%
+ {\begingroup
+ \edef\currentmathframed{#1}%
+ \dosingleempty\pack_framed_mathframed_indeed}
+
+\newcount\c_pack_framed_mathframed
+\newtoks \t_pack_framed_mathframed
+
+\def\pack_framed_math_pos
+ {\global\advance\c_pack_framed_mathframed\plusone
+ \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}%
+ \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mathframed}%
+ \xypos\pack_framed_mc_two}
+
+\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
+ {\iffirstargument
+ \setupcurrentmathframed[#1]%
+ \fi
+ \c_framed_mstyle\mathstyle
+ \edef\m_framed_location{\mathframedparameter\c!location}%
+ \ifx\m_framed_location\v!mathematics
+ \let\normalstrut\pack_framed_math_pos
+ \orelse\ifx\m_framed_location\v!low\else
+ \let\normalstrut\pack_framed_math_strut
+ \fi
+ \inheritedmathframedframed\bgroup
+ \Ustartmath
+ \triggermathstyle\c_framed_mstyle
+ \the\t_pack_framed_mathframed
+ #2%
+ \Ustopmath
+ \egroup
+ \endgroup}
+
+\appendtoks
+ \mathraggedstatus\plustwo % makes \startalign work
+ \eqalignmode \zerocount % makes \startalign fit
+\to \t_pack_framed_mathframed
+
+\installframedlocator \v!mathematics
+ {}
+ {\lower\dimexpr\MPy\pack_framed_mc_two-\MPy\pack_framed_mc_one\relax
+ \hpack{\xypos\pack_framed_mc_one\box\b_framed_normal}}
+
+\definemathframed[mframed]
+\definemathframed[inmframed][\c!location=\v!low]
+\definemathframed[mcframed] [\c!location=\v!mathematics]
+
+%D So instead of the rather versatile \type {\framed}, we use \type {\mframed}:
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y^{z_z}
+%D x \times \inmframed{y} \times y^{z_z}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D And:
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y^{\mframed{z}_{\mframed{z}}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D As usual, one can specify in what way the text should be framed. One should be
+%D aware of the fact that, inorder to preserve the proper spacing, the \type
+%D {offset} is set to \type {overlay} and \type {frameoffset} is used used instead.
+%D
+%D \startbuffer
+%D \startformula
+%D x \times y^{\mframed[framecolor=red]{z}_{z}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D For inline use, we also provide the \type {\inmframed} alternative: we want $x
+%D \times \inmframed{y}$ in inline math, right?
+
+%D This previous framing macros needs a lot of alternatives for putting rules around
+%D boxes, inserting offsets and aligning text. Each step is handled by separate macros.
+
+\newdimen\d_framed_applied_offset
+\newdimen\d_framed_loffset
+\newdimen\d_framed_roffset
+\newdimen\d_framed_toffset
+\newdimen\d_framed_boffset
+
+\def\pack_framed_check_extra_offsets % we could check h and v indepently
+ {\setfalse\c_framed_has_extra_offset
+ \d_framed_loffset\framedparameter\c!loffset\relax
+ \d_framed_roffset\framedparameter\c!roffset\relax
+ \d_framed_toffset\framedparameter\c!toffset\relax
+ \d_framed_boffset\framedparameter\c!boffset\relax
+ \ifzeropt\d_framed_loffset\else \advance\d_framed_width -\d_framed_loffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_roffset\else \advance\d_framed_width -\d_framed_roffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_toffset\else \advance\d_framed_height-\d_framed_toffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_boffset\else \advance\d_framed_height-\d_framed_boffset \settrue\c_framed_has_extra_offset \fi}
+
+\def\pack_framed_apply_extra_offsets
+ {\setbox\b_framed_normal\vpack\bgroup
+ \advance\d_framed_toffset\d_framed_applied_offset
+ \advance\d_framed_boffset\d_framed_applied_offset
+ \advance\d_framed_loffset\d_framed_applied_offset
+ \advance\d_framed_roffset\d_framed_applied_offset
+ \kern\d_framed_toffset
+ \hpack\bgroup
+ \kern\d_framed_loffset
+ \box\b_framed_normal
+ \kern\d_framed_roffset
+ \egroup
+ \kern\d_framed_boffset
+ \egroup}
+
+\def\pack_framed_widen_box
+ {\setbox\b_framed_normal\vpack
+ {\kern\d_framed_applied_offset
+ \hpack{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}%
+ \kern\d_framed_applied_offset}}
+
+%D Let's hope that the next few examples show us enough of what needs to be
+%D done by the auxiliary macros.
+%D
+%D \startbuffer
+%D \framed[height=1cm,offset=.5cm] {rule based learning}
+%D \framed[height=1cm,offset=0cm] {rule based learning}
+%D \framed[height=1cm,offset=none] {rule based learning}
+%D \framed[height=1cm,offset=overlay]{rule based learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D \startbuffer
+%D \framed[offset=.5cm] {rule based learning}
+%D \framed[offset=0cm] {rule based learning}
+%D \framed[offset=none] {rule based learning}
+%D \framed[offset=overlay]{rule based learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D \startbuffer
+%D \framed[strut=no,offset=.5cm] {rule based learning}
+%D \framed[strut=no,offset=0cm] {rule based learning}
+%D \framed[strut=no,offset=none] {rule based learning}
+%D \framed[strut=no,offset=overlay]{rule based learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D \startbuffer
+%D \framed[width=3cm,align=left] {rule\\based\\learning}
+%D \framed[width=3cm,align=middle] {rule\\based\\learning}
+%D \framed[width=3cm,align=right] {rule\\based\\learning}
+%D \framed[width=fit,align=middle] {rule\\based\\learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\dontcomplain\getbuffer}
+%D \stoplinecorrection
+%D
+%D So now we're ready for the complicated stuff. We distinguish between borders with
+%D straight lines and those with round corners. When using the first alternative it
+%D is possible to turn off one or more lines. More fancy shapes are also possible by
+%D specifying dedicated backgrounds. Turning lines on and off is implemented as
+%D efficient as possible and as a result is interface language dependant. This next
+%D implementation evolved from simpler ones. It puts for instance the rules on top
+%D of the content and provides additional offset capabilities. The lot of calls to
+%D other macros makes this mechanism not that easy to comprehend.
+%D
+%D We handle left, right or middle alignment as well as fixed or free widths and
+%D heights. Each combination gets its own macro.
+%D
+%D The following code handles one-liners: \type {align={line,flushright}}. Beware,
+%D since we entered a group and either or not grab the next bgroup token, we need to
+%D finish the group in the oneliner mode.
+
+\ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi
+
+\def\doformatonelinerbox % beware: assumes explicit preceding bgroup
+ {\ifconditional\raggedonelinerstate
+ \expandafter\dodoformatonelinerbox
+ \else
+ \expandafter\nodoformatonelinerbox
+ \fi}
+
+\def\dodoformatonelinerbox
+ {\afterassignment\redoformatonelinerbox
+ \setbox\nextbox\hbox} % maybe \hpack
+
+\def\redoformatonelinerbox
+ {\aftergroup\dododoformatonelinerbox
+ \ignorespaces}
+
+\def\dododoformatonelinerbox
+ {\hpack to \hsize % was \hbox
+ {\ifcase\raggedstatus\or\hss\or\hss \fi
+ \unhbox\nextbox \removeunwantedspaces
+ \ifcase\raggedstatus\or \or\hss\or\hss\fi}%
+ \egroup}
+
+\def\nodoformatonelinerbox % grabs {
+ {\let\next=}
+
+%D The handlers:
+
+% Beware, we have a \noindent so an empty line is indeed an empty line and
+% the \synchronizeinlinedirection triggers a vbox instead of a line.
+%
+% \startTEXpage[offset=0.5ex,align={lohi,middle}]
+%
+% \vbox{\hbox{x}}
+% \stopTEXpage
+%
+% \startTEXpage[offset=0.5ex,align={lohi,middle}]
+% \vbox{\hbox{x}}
+% \stopTEXpage
+
+% \def\pack_framed_forgetall{\forgetall}
+
+\def\pack_framed_set_foregroundcolor
+ {\edef\p_framed_foregroundcolor{\framedparameter\c!foregroundcolor}%
+ \ifx\p_framed_foregroundcolor\empty\else\dousecolorparameter\p_framed_foregroundcolor\fi}
+
+\def\pack_framed_do_setups
+ {\ifx\p_framed_setups\empty \else
+ \setups[\p_framed_setups]% \texsetup (or only one!)
+ % \fastsetup\p_framed_setup % singular would have been better
+ \fi}
+
+\def\pack_framed_format_format_yes
+ {\vbox to \d_framed_height
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \hsize\d_framed_width
+ \vsize\d_framed_height
+ \pack_framed_do_setups
+ \raggedcommand
+ \pack_framed_do_top
+ \bgroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\pack_framed_do_bottom
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_nop
+ {\vbox to \d_framed_height
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \hsize\d_framed_width
+ \vsize\d_framed_height
+ \pack_framed_do_setups
+ \raggedcenter
+ \vss
+ \bgroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_height
+ {\vbox to \d_framed_height
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \pack_framed_do_setups
+ \raggedcommand
+ \vss
+ \bgroup
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_width
+ {\vbox
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \hsize\d_framed_width
+ \pack_framed_do_setups
+ \raggedcommand
+ \pack_framed_do_top
+ \bgroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\pack_framed_do_bottom
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_vsize
+ {\vbox to \d_framed_height % no vpack .. maybe grid
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \vsize\d_framed_height
+ \pack_framed_do_setups
+ \vss
+ \bgroup
+ \aftergroup\vss
+ \aftergroup\egroup
+ \hbox
+ \bgroup
+ \aftergroup\egroup
+ \synchronizeinlinedirection
+ \localstrut
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_hsize
+ {\hbox to \d_framed_width
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \pack_framed_do_setups
+ \hss
+ \synchronizeinlinedirection
+ \localstrut
+ \bgroup
+ \aftergroup\hss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_no_size
+ {\hbox
+ \bgroup
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \let\postprocessframebox\relax
+ \pack_framed_do_setups
+ \synchronizeinlinedirection
+ \localstrut
+ \doformatonelinerbox}
+
+%D On the next page we show some examples of how these macros come into action. The
+%D examples show us how \type {fit}, \type {broad} dimensions influence the
+%D formatting. Watch the visualized struts. \footnote {Here we used \type
+%D {\showstruts}.}
+%D
+%D \startpostponing
+%D \bgroup
+%D \showstruts
+%D \dontcomplain
+%D \starttabulate[|c|c|c|c|c|c|]
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=yes] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=right] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=left] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=middle] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \stoptabulate
+%D \egroup
+%D \stoppostponing
+
+%D \macros
+%D {framednoflines, framedlastlength}
+%D
+%D It is possible to let the frame macro calculate the width of a centered box
+%D automatically (\type {fit}). When doing so, we need to reshape the box:
+
+\newcount\framednoflines
+\newdimen\framedfirstheight
+\newdimen\framedlastdepth
+\newdimen\framedminwidth
+\newdimen\framedmaxwidth
+\newdimen\framedaveragewidth
+
+\def\pack_framed_reshape_reset
+ {\framednoflines \zerocount
+ \framedfirstheight \zeropoint
+ \framedlastdepth \zeropoint
+ \framedminwidth \zeropoint
+ \framedmaxwidth \zeropoint
+ \framedaveragewidth\zeropoint}
+
+\def\pack_framed_reshape_process{\ifvbox\b_framed_normal\clf_doreshapeframedbox\b_framed_normal\relax\fi}
+\def\pack_framed_reshape_analyze{\ifvbox\b_framed_normal\clf_doanalyzeframedbox\b_framed_normal\relax\fi}
+
+% torture test / strange case (much depth) / method 2 needed
+%
+% \startTEXpage[frame=on]
+% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula
+% test outside formula
+% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula
+% \blank[big]
+% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula
+% test outside formula
+% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula
+% \stopTEXpage
+
+%D The examples on the next page show how one can give the frame as well as the
+%D background an additional offset and even a bit more depth. The blue outline is
+%D the frame, the red box is the background and the small black outline is the
+%D visualization of the resulting box, that is, we applied \type {\ruledhbox} to
+%D the result.
+%D
+%D \startpostponing
+%D \bgroup
+%D \unprotect
+%D \dontcomplain
+%D
+%D \startbuffer
+%D \unprotect
+%D \vbox to \vsize
+%D \bgroup
+%D \startalignment[middle]
+%D \vss
+%D \dontleavehmode\vbox to .8\vsize
+%D \bgroup
+%D \hsize=300pt
+%D \setupframed
+%D [background=color,
+%D backgroundcolorachtergrondkleur=darkred,
+%D width=300pt,
+%D height=60pt,
+%D framecolorkaderkleur=DemoBlue,
+%D rulethickness=2pt]
+%D \def\status%
+%D {backgroundoffset=\the\dimexpr\framedparameter\c!backgroundoffset\relax\\
+%D frameoffset=\the\dimexpr\framedparameter\c!frameoffset\relax\\
+%D depth=\the\dimexpr\framedparameter\c!depth\relax}
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=0pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=0pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=5pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=2pt,frameoffset=5pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=2pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=5pt]{\status}}
+%D \egroup
+%D \vss
+%D \stopalignment
+%D \egroup
+%D \protect
+%D \stopbuffer
+%D
+%D \getbuffer \page
+%D
+%D {\setupframed[depth=4pt]\getbuffer} \page
+%D
+%D \protect
+%D \egroup
+%D \stoppostponing
+
+%D We can draw lines from left to right and top to bottom by using the normal \type
+%D {\hairline} command. Both directions need a different treatment.
+%D
+%D \startbuffer
+%D \framed[width=4cm] {alfa\hairline beta\hairline gamma}
+%D \framed[height=2cm] {alfa\hairline beta\hairline gamma}
+%D \framed[width=4cm,height=2cm]{alfa\hairline beta\hairline gamma}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D These macros try to adapt their behaviour as good as possible to the circumstances
+%D and act as natural as possible.
+
+\unexpanded\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth
+ {\begingroup
+ \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
+ \scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax
+ \par
+ \nointerlineskip
+ \kern\scratchoffset
+ \dontleavehmode
+ \hrule\s!height\d_framed_linewidth\s!depth\zeropoint
+ \par
+ \kern-\d_framed_linewidth
+ \dontleavehmode
+ \hpack to \zeropoint{\hss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}%
+ \hfill
+ \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\hss}%
+ \par
+ \nointerlineskip
+ \kern\scratchoffset
+ \nointerlineskip
+ \endgraf
+ \nointerlineskip
+ \localbegstrut
+ \endgroup}
+
+\unexpanded\def\pack_framed_hboxed_hairline % use framed dimen
+ {\bgroup
+ \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
+ \ifconditional\c_framed_has_height
+ \dimen\scratchheight\dimexpr\localheight/\plustwo+\strutdp-\plustwo\d_framed_linewidth\relax
+ \dimen\scratchdepth \dimexpr\localheight/\plustwo-\strutdp+\plustwo\d_framed_linewidth\relax
+ \else
+ \dimen\scratchheight\dimexpr\strutht+\scratchoffset\relax
+ \dimen\scratchdepth \dimexpr\strutdp+\scratchoffset\relax
+ \fi
+ \unskip
+ \setbox\scratchbox\hpack
+ {\kern\scratchoffset
+ \vrule\s!height\dimen\scratchheight\s!depth\dimen\scratchdepth\s!width\d_framed_linewidth
+ \kern\scratchoffset}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \ignorespaces
+ \egroup}
+
+%D The argument of the frame command accepts \type{\\} as a sort of newline signal. In
+%D horizontal boxes it expands to a space.
+
+\unexpanded\def\pack_framed_vboxed_newline
+ {\endgraf\ignorespaces}
+
+\unexpanded\def\pack_framed_hboxed_newline
+ {\unskip\normalspace\ignorespaces}
+
+%D We can set each rule on or off. The default setting is inherited from
+%D \type {frame}. An earlier implementation use a bit different approach, but the new
+%D one seems more natural:
+%D
+%D \bgroup
+%D \setuptyping[margin=0pt]
+%D \startlinecorrection
+%D \startbuffer
+%D \framed[offset=overlay,frame=on]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=on,bottomframe=off]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=on,bottomframe=on]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=off]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=off,bottomframe=off]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=off,bottomframe=on]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D \stoplinecorrection
+%D \egroup
+
+%D \macros
+%D {startframedtext, setupframedtexts, defineframedtext}
+%D
+%D The general framing command we discussed previously, is not entirely suited for
+%D what we call framed texts, as for instance used in intermezzo's. The next
+%D examples show what we have in mind.
+%D
+%D \startbuffer[framed-0]
+%D \setupframedtexts
+%D [frame=off,
+%D width=\hsize,
+%D background=screen]
+%D
+%D \startframedtext
+%D By default the framed text is centered \dots
+%D \stopframedtext
+%D
+%D \startframedtext[right]
+%D \dots\ but we can also align left, middle and right.
+%D \stopframedtext
+%D \stopbuffer
+%D
+%D \startbuffer[framed-1]
+%D \defineframedtext
+%D [Example]
+%D [width=6cm,
+%D height=5cm]
+%D
+%D \startExample
+%D \typebuffer[framed-1]
+%D \stopExample
+%D \stopbuffer
+%D
+%D \startbuffer[framed-2]
+%D \defineframedtext
+%D [Example]
+%D [width=6cm]
+%D
+%D \startExample
+%D \typebuffer[framed-2]
+%D \stopExample
+%D \stopbuffer
+%D
+%D \startbuffer[framed-3]
+%D \defineframedtext
+%D [Example]
+%D [height=5cm]
+%D
+%D \startExample
+%D \typebuffer[framed-3]
+%D \stopExample
+%D \stopbuffer
+%D
+%D \startbuffer[framed-4]
+%D \defineframedtext
+%D [Example]
+%D [width=fit,height=broad]
+%D
+%D \Example{a very exciting example}
+%D \stopbuffer
+%D
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-0] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-1] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-2] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-3] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-4] \egroup
+%D
+%D Here we can see that we have a predefined framed text class as well as the
+%D tools for defining our own. So we have:
+%D
+%D \showsetup{setupframedtexts}
+%D
+%D as well as the definition command:
+%D
+%D \showsetup{defineframedtext}
+%D
+%D that generates two commands:
+%D
+%D \showsetup{start<<framedtext>>}
+%D \showsetup{<<framedtext>>}
+%D
+%D The next definition shows the defaults.
+
+\installcorenamespace{framedtext}
+\installcorenamespace{framedtextlocation}
+
+\installframedcommandhandler \??framedtext {framedtext} \??framedtext
+
+\let\setupframedtexts\setupframedtext
+
+\setupframedtext
+ [\c!width=.75\hsize,
+ \c!height=\v!fit,
+ \c!align=\v!yes,
+ %\c!top=,
+ \c!bottom=\vfill,
+ \c!offset=1em,
+ %\c!bodyfont=,
+ %\c!style=,
+ %\c!color=,
+ %\c!left=,
+ \c!right=\hfill,
+ \c!before=\blank,
+ \c!after=\blank,
+ %\c!inner=,
+ \c!frame=\v!on,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ %\c!orientation=,
+ %\c!indenting=,
+ %\c!foregroundcolor=,
+ %\c!foregroundstyle=,
+ %\c!background=,
+ %\c!backgroundcolor=,
+ \c!linecorrection=\v!on,
+ \c!depthcorrection=\v!on,
+ \c!margin=\v!standard]
+
+\appendtoks
+ \setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}%
+ \setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop }%
+ \setuevalue {\currentframedtext}{\pack_framed_text_direct{\currentframedtext}}%
+\to \everydefineframedtext
+
+\setvalue{\??framedtextlocation\v!left }{\letframedtextparameter\c!left \relax
+ \letframedtextparameter\c!right\hfill}
+
+\setvalue{\??framedtextlocation\v!right }{\letframedtextparameter\c!left \hfill
+ \letframedtextparameter\c!right\relax}
+
+\setvalue{\??framedtextlocation\v!middle}{\letframedtextparameter\c!left \hfill
+ \letframedtextparameter\c!right\hfill}
+
+\setvalue{\??framedtextlocation\v!none }{\letframedtextparameter\c!left \relax
+ \letframedtextparameter\c!right\relax
+ \settrue\c_framed_text_location_none}
+
+\unexpanded\def\pack_framed_text_start#1%
+ {\bgroup
+ \edef\currentframedtext{#1}%
+ \dodoubleempty\pack_framed_text_start_indeed}
+
+\def\pack_framed_text_start_indeed[#1][#2]%
+ {\doifelseassignment{#1}
+ {\pack_framed_text_start_continue\empty{#1}}
+ {\pack_framed_text_start_continue{#1}{#2}}}
+
+% todo: sort out first/lastline ht/dp
+
+\def\pack_framed_text_start_continue#1#2%
+ {\setupframedtexts[\currentframedtext][#2]%
+ \doifsomething{#1}{\setframedtextparameter\c!location{#1}}% does not listen to #3
+ \setfalse\c_framed_text_location_none
+ \csname\??framedtextlocation\framedtextparameter\c!location\endcsname
+ \resetframedtextparameter\c!location
+ \pack_framed_text_check
+ \setbox\b_framed_normal\vbox % \vpack
+ \startboxedcontent
+ \hsize\localhsize
+ % \insidefloattrue % ? better
+ \usebodyfontparameter\framedtextparameter
+ % \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used
+ \letframedtextparameter\c!strut\v!no
+ \inheritedframedtextframed\bgroup
+ \let\\=\endgraf
+ \edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}%
+ \ifx\p_framed_text_depthcorrection\v!on
+ \pack_framed_text_start_depth_correction
+ \else
+ \bgroup
+ \fi
+ \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1
+ \doinhibitblank
+ \useindentingparameter\framedtextparameter
+ \useframedtextstyleandcolor\c!style\c!color
+ \framedtextparameter\c!inner
+ \ignorespaces}
+
+% testcase 1:
+%
+% \showstruts
+% \startframedtext[align={normal,tolerant},offset=0pt] \input tufte \stopframedtext
+% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \input tufte \stopframedtext
+% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \inframed{x} \stopframedtext
+% \framed[align={normal,tolerant},offset=0pt]{\input tufte }
+
+%D The \type {none} option is handy for nested usage, as in the presentation
+%D styles, where we don't want interference.
+
+\defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext]
+
+\unexpanded\def\pack_framed_text_stop % no \baselinecorrection, see faq docs
+ {\endgraf
+ \removelastskip
+ \ifx\p_framed_text_depthcorrection\v!on
+ \pack_framed_text_stop_depth_correction
+ \else
+ \egroup
+ \fi
+ \stopboxedcontent
+ \ifconditional\c_framed_text_location_none
+ \egroup
+ \box\b_framed_normal
+ \orelse\ifinsidefloat
+ \egroup
+ \box\b_framed_normal
+ \else
+ \egroup
+ \placement[\??framedtext][\c!depthcorrection=\v!off]{\box\b_framed_normal}%
+ \fi
+ \egroup}
+
+%D We define the general (and original) case by just saying:
+
+\def\pack_framed_text_check % messy dependency
+ {\localhsize\hsize
+ \ifinsidefloat \orelse \ifdim\d_page_sides_vsize>\zeropoint % also possible: \c_page_sides_checks_done>\zeropoint
+ % \strut % rather clean way to invoke the sidefloat OTR
+ % \setbox0=\lastbox % and get the widths set, so from now on we
+ % \setlocalhsize % can have framed texts alongside sidefloats
+ \checksidefloat
+ \setlocalhsize
+ \fi}
+
+\def\pack_framed_text_start_depth_correction
+ {\bgroup
+ \ifhmode
+ \par
+ \fi
+ \ifvmode
+ \verticalstrut
+ % we need \nowhitespace in case of setups setting whitespace
+ % nb, not safe, text vs \vbox as next
+ \vskip-\struttotal
+ \nowhitespace
+ \fi} % na vskip ! new 20/05/2004, fails with next content being box (\scale{..})
+
+\def\pack_framed_text_stop_depth_correction
+ {\ifhmode
+ \par
+ \fi
+ \ifvmode
+ \forgetall
+ \vskip-\struttotal
+ \verticalstrut
+ \egroup
+ \forgetall % brrr too often
+ \vskip-\lineheight
+ \verticalstrut
+ \else
+ \egroup
+ \fi}
+
+%D Placement can be ignored:
+%D
+%D \starttyping
+%D \hbox to \hsize \bgroup
+%D \startframedtext[none][width=.5\textwidth] \input tufte \stopframedtext
+%D \startframedtext[none][width=.5\textwidth] \input zapf \stopframedtext
+%D \egroup
+%D
+%D \hbox to \hsize \bgroup
+%D \setupframedtexts[location=none]%
+%D \startframedtext[width=.5\textwidth] \input zapf \stopframedtext
+%D \startframedtext[width=.5\textwidth] \input tufte \stopframedtext
+%D \egroup
+%D \stoptyping
+
+%D The simple brace (or group) delimited case is typeset slightly different
+%D and is not aligned.
+
+\unexpanded\def\pack_framed_text_direct#1%
+ {\bgroup
+ \edef\currentframedtext{#1}%
+ \dosingleempty\pack_framed_text_start_direct}
+
+\def\pack_framed_text_start_direct[#1]%
+ {\usebodyfontparameter\framedtextparameter
+ \iffirstargument
+ \setupcurrentframedtext[#1]%
+ \fi
+ \edef\p_framed_text_strut{\framedtextparameter\c!strut}%
+ \letframedtextparameter\c!strut\v!no
+ \inheritedframedtextframed\bgroup
+ \blank[\v!disable]%
+ \let\\=\endgraf
+ \useframedtextstyleandcolor\c!style\c!color
+ \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1
+ \framedtextparameter\c!inner
+ \ifx\p_framed_text_strut\v!no
+ \let\pack_framed_strut\relax
+ \else
+ \let\pack_framed_strut\strut
+ \fi
+ \bgroup
+ \aftergroup\pack_framed_text_stop_direct
+ \afterassignment\ignorespaces
+ \afterassignment\pack_framed_strut
+ \let\next=}
+
+\def\pack_framed_text_stop_direct
+ {\removelastskip
+ \egroup
+ \egroup}
+
+\defineframedtext
+ [\v!framedtext]
+
+%D \macros
+%D {defineframed}
+%D
+%D One can also define simple framed texts, using:
+%D
+%D \showsetup{defineframed}
+%D
+%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance model instead
+%D of passing a combination of arguments. This also also simplified the \type
+%D {\setupframed} command. There are certainly more places where such improvements
+%D can be made.
+
+\appendtoks
+ \ifcsname\??regularframedlevel\currentframed\endcsname
+ % already defined, keeps settings
+ \else
+ \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname
+ \fi
+\to \everypresetframed
+
+\appendtoks
+ \setuevalue\currentframed{\pack_framed_defined_process[\currentframed]}%
+\to \everydefineframed
+
+\newcount\c_temp_framed_crap
+
+\unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent)
+ {\bgroup
+ \ifcsname\??regularframedlevel#1\endcsname
+ %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname
+ \expandafter\let\expandafter\c_pack_framed_temp\lastnamedcs
+ \else
+ \let\c_pack_framed_temp\c_temp_framed_crap
+ \fi
+ \advance\c_pack_framed_temp\plusone
+ \expandafter\def\csname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed
+ \bgroup
+ \edef\currentframed{#1>\the\c_pack_framed_temp}%
+ \pack_framed_initialize
+ \dosingleempty\pack_framed_defined_process_indeed}
+
+\def\pack_framed_defined_process_indeed[#1]%
+ {\iffirstargument % faster
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed}
+
+\let\placeframed\pack_framed_defined_process % new per 2012/04/23
+
+%D We can do:
+%D
+%D \starttyping
+%D \defineframed[\v!framed]
+%D \stoptyping
+%D
+%D but the existing one is ok as well (less csname messy too).
+
+%D New, for the moment private; let's see when GB finds out about this one and its
+%D obscure usage. It's used in:
+%D
+%D \startbuffer
+%D \defineframedtext
+%D [tabulateframe]
+%D [offset=overlay,
+%D backgroundoffset=3pt,
+%D background=color,
+%D backgroundcolor=green]
+%D
+%D \setuptabulate
+%D [tabulate]
+%D [frame=tabulateframe]
+%D
+%D \setuptables
+%D [frame=tabulateframe]
+%D
+%D \input tufte
+%D
+%D \starttabulate[|l|l|]
+%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR
+%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR
+%D \stoptabulate
+%D
+%D \input tufte
+%D
+%D \starttable[|l|l|]
+%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR
+%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\installcorenamespace{framedcontent}
+
+\installframedcommandhandler \??framedcontent {framedcontent} \??framedcontent
+
+\setupframedcontent
+ [\c!leftoffset=\zeropoint,
+ %\c!rightoffset=\framedcontentparameter\c!leftoffset,
+ \c!rightoffset=\scratchleftoffset,
+ \c!topoffset=\zeropoint,
+ %\c!bottomoffset=\framedcontentparameter\c!topoffset,
+ \c!bottomoffset=\scratchtopoffset,
+ \c!strut=\v!no,
+ %\c!linecorrection=\v!no,
+ %\c!left=,
+ %\c!right=,
+ %\c!width=\v!fit,
+ \c!offset=\v!overlay]
+
+\unexpanded\def\startframedcontent
+ {\dosingleempty\pack_framed_start_content}
+
+\def\pack_framed_start_content[#1]%
+ {\bgroup
+ \edef\currentframedcontent{#1}%
+ \ifx\currentframedcontent\v!off
+ \let\stopframedcontent\egroup
+ \else
+ \checkframedcontentparent
+ \let\stopframedcontent\pack_framed_stop_content_indeed
+ \expandafter\pack_framed_start_content_indeed
+ \fi}
+
+\def\pack_framed_start_content_indeed
+ {\setbox\b_framed_normal\hpack\bgroup
+ \setlocalhsize
+ \hsize\localhsize
+ \scratchleftoffset \framedcontentparameter\c!leftoffset \relax
+ \scratchrightoffset \framedcontentparameter\c!rightoffset \relax
+ \scratchtopoffset \framedcontentparameter\c!topoffset \relax
+ \scratchbottomoffset\framedcontentparameter\c!bottomoffset\relax
+ \advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax
+ \advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax
+ \kern\scratchleftoffset
+ \vpack\bgroup
+ \vskip\scratchtopoffset
+ \vbox\bgroup
+ \forgetall
+ \blank[\v!disable]}
+
+\def\pack_framed_stop_content_indeed
+ {\removelastskip
+ \egroup
+ \vskip\scratchbottomoffset
+ \egroup
+ \kern\scratchrightoffset
+ \egroup
+ \doif{\framedcontentparameter\c!width}\v!fit
+ {\letframedcontentparameter\c!width\v!fixed}% no shapebox
+ \ifinsidefloat
+ \donefalse
+ \else
+ \doifelse{\framedcontentparameter\c!linecorrection}\v!yes\donetrue\donefalse
+ \fi
+ % plaats ?
+ \ifdone\startlinecorrection\fi
+ \framedcontentparameter\c!left % new
+ \inheritedframedcontentframed{\box\b_framed_normal}% hm
+ \framedcontentparameter\c!right % new
+ \ifdone\stoplinecorrection\fi
+ \egroup}
+
+% A shared setting.
+
+\setuplinewidth
+ [\v!medium]
+
+%D A Goodie:
+
+\def\v!unframed{unframed}
+
+\defineframed
+ [\v!unframed]
+ [\c!frame=\v!off,
+ \c!rulethickness=\zeropoint,
+ \c!foregroundstyle=\framedparameter\c!style,
+ \c!foregroundcolor=\framedparameter\c!color]
+
+%D Bonus (as defined in \type {pack-rul.lua}):
+%D
+%D \starttyping
+%D \setbox\scratchbox\vbox{a\par aa\par aaa\par}
+%D \the\dimexpr\themaxboxwidth\scratchbox\relax
+%D \stoptyping
+
+\let\themaxboxwidth\clf_themaxboxwidth
+
+%D New: slow but ok for most cases:
+
+\unexpanded\def\doifelseframed#1%
+ {\ifcase\numexpr\zerocount
+ \immediateassignment\edef\tempstring{#1\c!frame }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!topframe }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!bottomframe}\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!leftframe }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!rightframe }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!background }\ifx\tempstring\empty\else+\plusone\fi
+ \relax\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/page-imp.mkiv b/tex/context/base/mkiv/page-imp.mkiv
index 2f4e9a2f9..b65f8991a 100644
--- a/tex/context/base/mkiv/page-imp.mkiv
+++ b/tex/context/base/mkiv/page-imp.mkiv
@@ -162,11 +162,15 @@
\box\scratchbox
\endgroup}
-\ifdefined \page_shipout_box \else
+%D Also in normal \MKIV\ we nos use the indirect way so that we benefit from timing and
+%D tracing.
- \def\page_shipout_box#1{\normalshipout\box#1\relax} % takes a number
+% \def\page_shipout_box#1{\normalshipout\box#1\relax} % takes a number
-\fi
+\unexpanded\def\page_shipout_box#1%
+ {\clf_shipoutpage#1\relax
+ \global\setbox#1\emptybox
+ \global\deadcycles\zerocount}
\def\page_shipouts_normal#1%
{\global\advance\shippedoutpages\plusone
diff --git a/tex/context/base/mkiv/scrn-wid.mkvi b/tex/context/base/mkiv/scrn-wid.mkvi
index b92880f2e..6808bd0b3 100644
--- a/tex/context/base/mkiv/scrn-wid.mkvi
+++ b/tex/context/base/mkiv/scrn-wid.mkvi
@@ -25,6 +25,8 @@
%D As usual in \CONTEXT\ we separate the general definition (frontend)
%D and the rendering (backend).
+% hack: x\footnote{x\inleftmargin[scope=local]{\attachment[location=high,file=i-context.pdf]}}x
+
% old but stil valid method:
%
% \useattachment[test.tex]
diff --git a/tex/context/base/mkiv/spac-ver.mkiv b/tex/context/base/mkiv/spac-ver.mkiv
index c76555cba..bf9427199 100644
--- a/tex/context/base/mkiv/spac-ver.mkiv
+++ b/tex/context/base/mkiv/spac-ver.mkiv
@@ -2127,38 +2127,13 @@
\installcorenamespace{vspacing}
-\startmkivmode
-
- \unexpanded\def\directvspacing#1%
- {\par
- \ifcsname\??vspacing#1\endcsname
- \lastnamedcs
- \else
- \spac_vspacing_yes_preset{#1}%
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\directvspacing#1%
- {\par
- \ifchkdim#1\or
- \spac_vspacing_dim_preset{\the\dimexpr#1}%
- \else\ifcsname\??vspacing#1\endcsname
- \lastnamedcs
- \else
- \spac_vspacing_yes_preset{#1}%
- \fi\fi}
-
- \def\spac_vspacing_dim_preset#1%
- {\ifcsname\??vspacing#1\endcsname
- \lastnamedcs
- \else
- \spac_vspacing_yes_preset{#1}%
- \fi}
-
-\stoplmtxmode
+\unexpanded\def\directvspacing#1%
+ {\par
+ \ifcsname\??vspacing#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspacing_yes_preset{#1}%
+ \fi}
\def\spac_vspacing_yes_preset#1%
{\setxvalue{\??vspacing#1}{\clf_vspacing{#1}}%
diff --git a/tex/context/base/mkiv/spac-ver.mkxl b/tex/context/base/mkiv/spac-ver.mkxl
new file mode 100644
index 000000000..d15105e80
--- /dev/null
+++ b/tex/context/base/mkiv/spac-ver.mkxl
@@ -0,0 +1,2597 @@
+%D \module
+%D [ file=spac-ver,
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Vertical,
+%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.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Vertical}
+
+\unprotect
+
+\registerctxluafile{spac-ver}{optimize}
+
+% todo: use usernodes ?
+
+% todo: itemize : intro ... only when there is one or two lines preceding and then
+% keep these together i.e. \blank[intro]
+
+% Isn't it about time to get rid of topskip i.e. make it equivalent to
+% \openstrutheight so that we can remove delta code.
+%
+% There might be more namespace protection.
+
+%D There are two ways to influence the interline spacing. The most general and often
+%D most consistent way is using
+%D
+%D \showsetup{setupinterlinespace}
+%D
+%D For instance
+%D
+%D \starttyping
+%D \setupinterlinespace[line=2.8ex]
+%D \stoptyping
+%D
+%D This setting adapts itself to the bodyfontsize, while for instance saying
+%D
+%D \starttyping
+%D \setupinterlinespace[line=12pt]
+%D \stoptyping
+%D
+%D sets things fixed for all sizes, which is definitely not what we want. Therefore
+%D one can also say:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[9pt][interlinespace=11pt]
+%D \stoptyping
+%D
+%D One can still use \type {\setupinterlinespace} (without arguments) to set the
+%D interline space according to the current font, e.g. a \type {\bfa}.
+
+% will be cleaned up but it will stay messy because we accept so
+% many variants
+
+\newif\iflocalinterlinespace
+
+\newskip \s_spac_vspacing_temp \s_spac_vspacing_temp\bigskipamount
+
+\def\skipfactor {.75}
+\def\skipgluefactor{.25}
+
+\def\normalskipamount
+ {\openlineheight
+ \ifgridsnapping \else \ifblankflexible
+ \s!plus \skipgluefactor\openlineheight
+ \s!minus\skipgluefactor\openlineheight
+ \fi \fi
+ \relax}
+
+\ifdefined\bodyfontinterlinespace \else
+ \let\bodyfontinterlinespace\empty
+\fi
+
+\unexpanded\def\presetnormallineheight % each bodyfont
+ {\edef\normallineheight{\interlinespaceparameter\c!line}%
+ \iflocalinterlinespace \else
+ \edef\m_spac_normallineheight{\bodyfontinterlinespace}%
+ \ifx\m_spac_normallineheight\empty \else
+ \let\normallineheight\m_spac_normallineheight
+ \fi
+ \fi}
+
+\unexpanded\def\setupspecifiedinterlinespace[#1]%
+ {\setupcurrentinterlinespace[#1]%
+ \spac_linespacing_setup_specified_interline_space}
+
+\def\spac_linespacing_setup_specified_interline_space
+ {\edef\strutheightfactor {\interlinespaceparameter\c!height }%
+ \edef\strutdepthfactor {\interlinespaceparameter\c!depth }%
+ \edef\minimumstrutheight {\interlinespaceparameter\c!minheight}%
+ \edef\minimumstrutdepth {\interlinespaceparameter\c!mindepth }%
+ \edef\minimumlinedistance {\interlinespaceparameter\c!distance }%
+ \edef\normallineheight {\interlinespaceparameter\c!line }%
+ \edef\topskipfactor {\interlinespaceparameter\c!top }%
+ \edef\maxdepthfactor {\interlinespaceparameter\c!bottom }%
+ \edef\m_spac_vertical_baseline_stretch_factor{\interlinespaceparameter\c!stretch }%
+ \edef\m_spac_vertical_baseline_shrink_factor {\interlinespaceparameter\c!shrink }%
+ % often topskip does more bad than good, so:
+ \ifx\topskipfactor\v!height
+ \let\topskipfactor\strutheightfactor
+ \fi
+ \setfontparameters % redundant, can be \setstrut, test first
+ \updateraggedskips} % yes indeed
+
+\installcorenamespace{interlinespacerelative}
+
+\let\setrelativeinterlinespace \relax % used elsewhere
+\let\currentrelativeinterlinespace\empty
+
+\setvalue{\??interlinespacerelative\v!on }{\oninterlineskip}
+\setvalue{\??interlinespacerelative\v!off }{\offinterlineskip}
+\setvalue{\??interlinespacerelative\v!reset}{\let\currentrelativeinterlinespace\empty
+ \let\setrelativeinterlinespace\relax
+ \setfontparameters}
+\setvalue{\??interlinespacerelative\v!auto }{\let\setrelativeinterlinespace\spac_linespacing_set_relative_interlinespace}
+
+\def\spac_linespacing_set_specified_relative_interlinespace#1% fragile?
+ {\doifelsedimenstring{#1}
+ {\setupspecifiedinterlinespace[\c!line=#1]}
+ {\assignvalue{#1}\currentrelativeinterlinespace{1.00}{1.25}{1.50}%
+ \spacing\currentrelativeinterlinespace}}
+
+\unexpanded\def\setuprelativeinterlinespace[#1]%
+ {\processcommalist[#1]\spac_linespacing_setup_relative_interlinespace}
+
+\def\spac_linespacing_setup_relative_interlinespace#1%
+ {\ifcsname\??interlinespacerelative#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_linespacing_set_specified_relative_interlinespace{#1}%
+ \fi}
+
+\def\spac_linespacing_set_relative_interlinespace
+ {\ifx\currentrelativeinterlinespace\empty\else
+ \spacing\currentrelativeinterlinespace
+ \fi}
+
+\unexpanded\def\spac_linespacing_setup_use
+ {\ifcsname\namedinterlinespacehash\m_spac_interlinespace\s!parent\endcsname
+ \let\currentinterlinespace\m_spac_interlinespace
+ \spac_linespacing_setup_specified_interline_space
+ % \else
+ % we only support named interlinespaces
+ \fi}
+
+\unexpanded\def\useinterlinespaceparameter#1% see footnotes
+ {\edef\m_spac_interlinespace{#1\c!interlinespace}%
+ \ifx\m_spac_interlinespace\empty \else
+ \spac_linespacing_setup_use
+ \fi}
+
+\newtoks\everysetupglobalinterlinespace
+\newtoks\everysetuplocalinterlinespace
+
+\newconditional\interlinespaceisset
+
+\installcorenamespace{interlinespace}
+
+\installcommandhandler \??interlinespace {interlinespace} \??interlinespace
+
+\installmacrostack\currentinterlinespace
+
+\unexpanded\def\setupinterlinespace
+ {\dodoubleempty\spac_linespacing_setup}
+
+\ifdefined\setupinterlinespace_double \else
+ \let\setupinterlinespace_double\setup_interlinespace % for a while
+\fi
+
+\def\spac_linespacing_setup[#1][#2]%
+ {\settrue\interlinespaceisset % reset has to be done when needed
+ \ifsecondargument
+ \setupinterlinespace_double[#1][#2]%
+ \orelse\iffirstargument
+ \ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname
+ \edef\currentinterlinespace{#1}%
+ \spac_linespacing_setup_specified_interline_space
+ %\dosetupspecifiedinterlinespaceindeed
+ \else
+ \spac_linespacing_setup_specified_or_relative[#1]%
+ \fi
+ \else
+ \let\currentinterlinespace\empty
+ \spac_linespacing_synchronize_local
+ \fi}
+
+\def\spac_linespacing_setup_specified_or_relative[#1]%
+ {\doifelseassignment{#1}\setupspecifiedinterlinespace\setuprelativeinterlinespace[#1]%
+ \the\iflocalinterlinespace\everysetuplocalinterlinespace\else\everysetupglobalinterlinespace\fi}
+
+\def\spac_linespacing_synchronize_local % adapts to the font
+ {\localinterlinespacetrue
+ \setfontparameters
+ \updateraggedskips % funny one here
+ \the\everysetuplocalinterlinespace
+ \localinterlinespacefalse}
+
+\unexpanded\def\dosetupcheckedinterlinespace#1% often a chain
+ {\edef\p_spac_checked_interlinespace{#1}%
+ \ifx\p_spac_checked_interlinespace\empty
+ \spac_linespacing_synchronize_local
+ \orelse\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check
+ \push_macro_currentinterlinespace
+ \let\currentinterlinespace\p_spac_checked_interlinespace
+ \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed
+ \iflocalinterlinespace
+ \the\everysetuplocalinterlinespace
+ \else
+ \localinterlinespacetrue
+ \the\everysetuplocalinterlinespace
+ \localinterlinespacefalse
+ \fi
+ \pop_macro_currentinterlinespace
+ \else
+ \normalexpanded{\noexpand\doifelseassignment{\p_spac_checked_interlinespace}%
+ \setupspecifiedinterlinespace\setuprelativeinterlinespace[\p_spac_checked_interlinespace]}%
+ \iflocalinterlinespace
+ \the\everysetuplocalinterlinespace
+ \else
+ \localinterlinespacetrue
+ \the\everysetuplocalinterlinespace
+ \localinterlinespacefalse
+ \fi
+ \fi}
+
+\unexpanded\def\setuplocalinterlinespace[#1]%
+ {\localinterlinespacetrue
+ \push_macro_currentinterlinespace
+ \setupinterlinespace[#1]%
+ \pop_macro_currentinterlinespace
+ \localinterlinespacefalse}
+
+\let\switchtointerlinespace\setuplocalinterlinespace
+
+%D Helpers
+
+\newskip \s_spac_lastskip
+\newdimen\d_spac_prevdepth
+\newcount\c_spac_spacefactor
+\newdimen\d_spac_prevcontent % set by lua
+
+\unexpanded\def\removelastskip
+ {\ifvmode\ifdim\lastskip=\zeropoint\else\vskip-\lastskip\fi\fi}
+
+\def\doifoutervmode
+ {\ifvmode
+ \ifinner
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \doubleexpandafter\firstofoneargument
+ \fi
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\dosomebreak#1%
+ {\doifoutervmode
+ {\s_spac_lastskip\lastskip
+ \removelastskip
+ #1\relax
+ \ifdim\s_spac_lastskip=\zeropoint
+ % avoid interference with footnotes
+ \else
+ \vskip\s_spac_lastskip
+ \fi}}
+
+\unexpanded\def\packed
+ {\nointerlineskip}
+
+\unexpanded\def\godown[#1]%
+ {\relax
+ \ifhmode\endgraf\fi
+ \ifvmode\nointerlineskip\vskip#1\relax\fi}
+
+\unexpanded\def\smallskip{\vskip\smallskipamount}
+\unexpanded\def\medskip {\vskip\medskipamount}
+\unexpanded\def\bigskip {\vskip\bigskipamount}
+
+\unexpanded\def\smallbreak
+ {\par
+ \ifvmode\ifdim\lastskip<\smallskipamount
+ \removelastskip
+ \penalty-\plusfifty
+ \smallskip
+ \fi\fi}
+
+\unexpanded\def\medbreak
+ {\par
+ \ifvmode\ifdim\lastskip<\medskipamount
+ \removelastskip
+ \penalty-\plusonehundred
+ \medskip
+ \fi\fi}
+
+\unexpanded\def\bigbreak
+ {\par
+ \ifvmode\ifdim\lastskip<\bigskipamount
+ \removelastskip
+ \penalty-\plustwohundred
+ \bigskip
+ \fi\fi}
+
+\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode
+\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode
+\unexpanded\def\allowbreak{\penalty \zerocount} % can be hmode or vmode
+
+\unexpanded\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode
+\unexpanded\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode
+
+%D Made slightly more readable:
+
+\unexpanded\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=}
+\unexpanded\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=}
+\unexpanded\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi}
+
+\def\spac_helpers_vglue_indeed
+ {\par
+ \ifvmode
+ \d_spac_prevdepth\prevdepth
+ \hrule\s!height\zeropoint
+ \nobreak
+ \vskip\s_spac_lastskip
+ \prevdepth\d_spac_prevdepth
+ \fi}
+
+\def\spac_helpers_hglue_indeed
+ {\dontleavehmode
+ \c_spac_spacefactor\spacefactor
+ \vrule\s!width\zeropoint
+ \nobreak
+ \hskip\s_spac_lastskip
+ \spacefactor\c_spac_spacefactor}
+
+%D We adapt plain's \type {\removelastskip} a bit:
+
+\unexpanded\def\removelastskip % also in supp-box
+ {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
+
+% The whitespace handler. We could cache settings but normally there are not
+% that many in a set.
+
+\installcorenamespace{whitespacemethod}
+
+\newskip \s_spac_whitespace_parskip \s_spac_whitespace_parskip\zeropoint
+\newconditional\c_spac_whitespace_flexible \settrue\c_spac_whitespace_flexible
+\newconstant \c_spac_whitespace_grid_mode % option in layout / 1=permit_half_lines
+
+%def\v_spac_whitespace_current{\zeropoint}
+\let\v_spac_whitespace_current\v!none
+
+\unexpanded\def\setupwhitespace
+ {\doifelsenextoptionalcs\spac_whitespace_setup_yes\spac_whitespace_setup_nop}
+
+\def\spac_whitespace_setup_nop
+ {\ifx\v_spac_whitespace_current\v!none\else
+ \spac_whitespace_setup
+ \fi}
+
+\let\synchronizewhitespace\spac_whitespace_setup_nop
+
+\def\spac_whitespace_setup_yes[#1]%
+ {\edef\m_spac_whitespace_asked{#1}%
+ \ifx\m_spac_whitespace_asked\empty
+ \spac_whitespace_setup_nop
+ \else
+ \let\v_spac_whitespace_current\m_spac_whitespace_asked
+ \spac_whitespace_setup
+ \fi}
+
+\def\spac_whitespace_setup % quick test for no list
+ {\ifcsname\??whitespacemethod\v_spac_whitespace_current\endcsname
+ \lastnamedcs
+ \else
+ \expandafter\processcommalist\expandafter[\v_spac_whitespace_current]\spac_whitespace_setup_method % can be raw
+ \fi\relax
+ \ifgridsnapping
+ \spac_whitespace_setup_grid
+ \else
+ \spac_whitespace_setup_normal
+ \fi
+ \parskip\s_spac_whitespace_parskip}
+
+\def\spac_whitespace_setup_normal
+ {\ifconditional\c_spac_whitespace_flexible \else
+ \s_spac_whitespace_parskip\plusone\s_spac_whitespace_parskip
+ \fi}
+
+\def\spac_whitespace_setup_grid
+ {\setfalse\c_spac_whitespace_flexible
+ \ifdim\s_spac_whitespace_parskip>\zeropoint
+ \s_spac_whitespace_parskip
+ \ifcase\c_spac_whitespace_grid_mode
+ \baselineskip
+ \or
+ \ifdim\scratchdimen=\baselineskip % maybe range
+ \baselineskip
+ \else
+ \numexpr\s_spac_whitespace_parskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
+ \fi
+ \else
+ \baselineskip
+ \fi
+ \fi}
+
+\unexpanded\def\installwhitespacemethod#1#2%
+ {\setvalue{\??whitespacemethod#1}{#2}}
+
+\installwhitespacemethod \v!fix {}
+\installwhitespacemethod \v!fixed {\setfalse\c_spac_whitespace_flexible}
+\installwhitespacemethod \v!flexible {\settrue \c_spac_whitespace_flexible}
+
+\installwhitespacemethod \v!line {\s_spac_whitespace_parskip \baselineskip}
+\installwhitespacemethod \v!halfline {\s_spac_whitespace_parskip .5\baselineskip}
+\installwhitespacemethod \v!quarterline {\s_spac_whitespace_parskip.25\baselineskip}
+\installwhitespacemethod \v!none {\s_spac_whitespace_parskip \zeropoint}
+\installwhitespacemethod \v!big {\s_spac_whitespace_parskip \bigskipamount}
+\installwhitespacemethod \v!medium {\s_spac_whitespace_parskip \medskipamount}
+\installwhitespacemethod \v!small {\s_spac_whitespace_parskip \smallskipamount}
+
+\installwhitespacemethod \s!default {\spac_whitespace_setup_nop} % also covers none
+
+\def\spac_whitespace_setup_method#1%
+ {\ifcsname\??whitespacemethod#1\endcsname
+ \lastnamedcs
+ \else
+ \s_spac_whitespace_parskip#1\fi
+ \relax}
+
+\unexpanded\def\forgetparskip
+ {\s_spac_whitespace_parskip\zeropoint
+ \parskip\zeropoint
+ \let\v_spac_whitespace_current\v!none}
+
+\appendtoks
+ \forgetparskip
+\to \everyforgetall
+
+% \installwhitespacemethod \s!unknown {\s_spac_whitespace_parskip\commalistelement\relax}
+%
+% \def\spac_whitespace_setup_method#1%
+% {\csname\??whitespacemethod\ifcsname\??whitespacemethod#1\endcsname#1\else\s!unknown\endcsname\relax}
+
+\unexpanded\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]}
+\unexpanded\def\whitespace {\directcheckedvspacing\v!white} % {\vspacing[\v!white]}
+
+\setupwhitespace
+ [\v!none]
+
+% Packed:
+
+% todo: when packed blocks blank, we need to enable forced
+
+\newconditional\c_spac_packed_blank \settrue\c_spac_packed_blank
+\newcount \c_spac_packed_level
+
+\unexpanded\def\startpacked
+ {\dosingleempty\spac_packed_start}
+
+\def\spac_packed_start[#1]% nesting afvangen
+ {\global\advance\c_spac_packed_level\plusone
+ \par
+ \ifnum\c_spac_packed_level=\plusone \ifvmode
+ \begingroup
+ \whitespace % not combined
+ \directcheckedvspacing\v!disable % \blank[\v!disable]% or \inhibitblank
+ \doifelse{#1}\v!blank\settrue\setfalse\c_spac_packed_blank
+ \setupwhitespace[\v!none]% or \forgetparskip
+ \fi \fi}
+
+\unexpanded\def\stoppacked
+ {\par
+ \ifnum\c_spac_packed_level=\plusone \ifvmode
+ \endgroup
+ \fi \fi
+ \global\advance\c_spac_packed_level\minusone}
+
+\unexpanded\def\startunpacked
+ {\directdefaultvspacing % \blank
+ \begingroup}
+
+\unexpanded\def\stopunpacked
+ {\endgroup
+ \directdefaultvspacing}% \blank}
+
+% \prevdepth crosses pageboundaries!
+%
+% todo: a version that works ok inside a box
+
+% global : outer hsize + keep skips
+% local : inner hsize + reset skips
+
+\installcorenamespace{linesaround}
+
+\let\spac_lines_vbox\vbox
+
+\installtextracker
+ {linecorrection.boxes}
+ {\let\spac_lines_vbox\ruledvbox}
+ {\let\spac_lines_vbox\vbox}
+
+\let\v_spac_lines_around_action_set\relax
+\let\m_spac_lines_around \empty
+
+\newconstant\c_spac_lines_correction_mode
+
+\setvalue{\??linesaround\v!blank }{\blank}
+\letvalue{\??linesaround\empty }\relax
+\setvalue{\??linesaround\s!unknown}{\directcheckedvspacing\m_spac_lines_around} % \blank[\m_spac_lines_around]}
+
+\def\spac_lines_action_around % we used to let this one but it's cleaner this way
+ {\csname\??linesaround % i.e. do it twice
+ \ifcsname\??linesaround\m_spac_lines_around\endcsname\m_spac_lines_around\else\s!unknown\fi
+ \endcsname}
+
+\unexpanded\def\startlinecorrection
+ {\endgraf
+ \begingroup
+ \setconstant\c_spac_lines_correction_mode\plusone
+ \dosingleempty\spac_lines_start_correction}
+
+\unexpanded\def\startlocallinecorrection
+ {\endgraf
+ \begingroup
+ \setconstant\c_spac_lines_correction_mode\plustwo
+ \dosingleempty\spac_lines_start_correction}
+
+\unexpanded\def\spac_lines_start_correction[#1]%
+ {\edef\m_spac_lines_around{#1}%
+ \spac_lines_action_around
+ \d_spac_prevdepth\prevdepth
+ \spac_lines_initialize_corrections
+ \offbaselinecorrection % ???
+ \setbox\scratchbox\spac_lines_vbox\bgroup
+ \ifcase\c_spac_lines_correction_mode
+ % nothing
+ \or
+ % global
+ \or
+ % local
+ \setlocalhsize
+ \hsize\localhsize
+ \forgetbothskips
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\spac_lines_stop_correction
+ {\removeunwantedspaces
+ \egroup
+ \ifgridsnapping
+ \spac_lines_stop_correction_ongrid
+ \else
+ \spac_lines_stop_correction_normal
+ \fi
+ \endgroup}
+
+\unexpanded\def\spac_lines_stop_correction_ongrid
+ {\directcheckedvspacing\v!white % \blank[\v!white]%
+ \spac_lines_action_around
+ \snaptogrid\hpack{\box\scratchbox}%
+ \directcheckedvspacing\v!white
+ \spac_lines_action_around}
+
+\unexpanded\def\spac_lines_stop_correction_normal
+ {\directcheckedvspacing\v!nowhite % \blank[\v!nowhite]%
+ \ifdim\parskip>\zeropoint
+ % too fuzzy otherwise
+ \else
+ % doesn't like whitespace
+ \ifdim\d_spac_prevdepth<\maxdimen
+ \unless\ifdim\d_spac_prevdepth<\zeropoint
+ \ifdim\d_spac_prevdepth<\strutdp \relax
+ \pushlastnode
+ \ifdim\d_spac_prevdepth>\zeropoint
+ \kern-\d_spac_prevdepth
+ \fi
+ \kern\strutdp
+ \prevdepth\strutdp
+ \poplastnode
+ \fi
+ \fi
+ \fi
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ % \blank[\v!white,\the\d_spac_lines_correction_before]% \blank[\v!white]\dotopbaselinecorrection
+ \directcheckedvspacing{\v!white,\the\d_spac_lines_correction_before}% \blank[\v!white]\dotopbaselinecorrection
+ \fi
+ \nointerlineskip % new
+ \noindent % not \dontleavehmode !
+ \ifcase\c_spac_lines_correction_mode
+ % nothing
+ \or
+ % global
+ \hskip-\leftskip % more tricky would be hangindent so we ignore that one
+ \or
+ % local
+ \fi
+ \box\scratchbox
+ \endgraf
+ %
+ % eventually i'll get it right ... (i also need to check all whitespace code elsewhere)
+ %
+ % \blank[\the\d_spac_lines_correction_after]% \dobotbaselinecorrection
+ % \directcheckedvspacing{\the\d_spac_lines_correction_after}% \dobotbaselinecorrection
+ \directcheckedvspacing{\v!white,\the\d_spac_lines_correction_after}% \dobotbaselinecorrection
+ % \allowbreak % new, otherwise problems when many in a row
+ \prevdepth\strutdp
+ \spac_lines_action_around}
+
+\let\stoplinecorrection \spac_lines_stop_correction
+\let\stoplocallinecorrection\spac_lines_stop_correction
+
+% todo:
+
+\unexpanded\def\correctwhitespace
+ {\dowithnextboxcs\correctwhitespacefinish\vbox}
+
+\unexpanded\def\correctwhitespacefinish
+ {\startbaselinecorrection
+ \flushnextbox
+ \stopbaselinecorrection}
+
+\unexpanded\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}}
+\unexpanded\def\horizontalstrut{\hpack {\strut}}
+
+%D Here follow some presets related to interline spacing and therefore also struts.
+%D The values 2.8, 0.07, 0.72 and 0.28 originate in \INRSTEX, a package that we used
+%D a while after we decided that \LATEX\ was not flexible enough. After that
+%D \CONTEXT\ evolved, from some wrapper code around (old) \LATEX\ (on a floppy
+%D disk), to using modules from \INRSTEX\ (which also fit on a floppy) and finally
+%D all written from scratch. I simply didn't understand all that \TEX\ code at that
+%D time, and it was easier to figure it out myself. But \unknown\ some settings
+%D stayed, as the height|/|depth ratios, and they never proved to be bad ones! The
+%D same is true for the font size relations.
+
+%D \starttabulate
+%D \NC \type {\lineheight} \NC the height of a line \NC \NR
+%D \NC \type {\spacing{number}} \NC adapting the interline space \NC \NR
+%D \NC \type {\normalbaselines} \NC initialize the interline spacing \NC \NR
+%D \NC \type {\setstrut} \NC initialize \type {\strut} \NC \NR
+%D \NC \type {\setnostrut} \NC disable the \type {\strut}, \type {\endstrut}, \type {\begstrut} \NC \NR
+%D \NC \type {\setteststrut} \NC initialize the visual \type {\strut} \NC \NR
+%D \NC \type {\resetteststrut} \NC disable the visual \type {\strut} \NC \NR
+%D \NC \type {\setfontparameters} \NC synchronize parameters with foints \NC \NR
+%D \stoptabulate
+%D
+%D \unknown\ and many more (this is a decades old list).
+%D
+%D The lineheight is the sum of the height and depth of \type {strut}, which is
+%D an invisible blob that can be used to enforce the proper dimensions.
+%D
+%D Such a blob, when placed at the beginning of a paragraph can have side effects
+%D that can be prevented with \type {\dontleavehmode}. Never use \type
+%D {\leavevmode}!
+
+\newdimen\strutdimen
+\newdimen\lineheight
+\newdimen\openlineheight
+\newdimen\openstrutheight
+\newdimen\openstrutdepth
+\newdimen\topskipgap
+\newdimen\struttotal
+
+\def\strutheightfactor {.72}
+\def\strutdepthfactor {.28}
+
+\def\baselinefactor {2.8}
+
+\let\m_spac_vertical_baseline_stretch_factor \zerocount
+\let\m_spac_vertical_baseline_shrink_factor \zerocount
+
+\def\minimumstrutheight {\zeropoint}
+\def\minimumstrutdepth {\zeropoint}
+
+\def\normallineheight {\baselinefactor\exheight}
+\def\minimumlinedistance {\lineskip}
+
+\def\strutheight {\zeropoint}
+\def\strutdepth {\zeropoint}
+\def\strutwidth {\zeropoint}
+
+\let\spacingfactor \plusone
+
+\def\topskipfactor {1.0}
+\def\maxdepthfactor {0.5}
+
+\def\systemtopskipfactor {\topskipfactor}
+\def\systemmaxdepthfactor {\maxdepthfactor}
+
+\ifdefined\globalbodyfontsize \else
+ \newdimen\globalbodyfontsize
+ \globalbodyfontsize=12pt
+\fi
+
+\ifdefined\normalizedbodyfontsize \else
+ \def\normalizedbodyfontsize{12pt}
+\fi
+
+\unexpanded\def\topskipcorrection
+ {\simpletopskipcorrection
+ \vskip-\struttotal
+ \verticalstrut}
+
+\unexpanded\def\simpletopskipcorrection
+ {\ifdim\topskip>\openstrutheight
+ % == \vskip\topskipgap
+ \vskip\topskip
+ \vskip-\openstrutheight
+ \fi}
+
+\unexpanded\def\settopskip % the extra test is needed for the lbr family
+ {\topskip
+ \ifgridsnapping
+ \zeropoint
+ \else
+ \systemtopskipfactor\globalbodyfontsize
+ \ifcase\bottomraggednessmode % ragged bottom
+ \s!plus5\globalbodyfontsize
+ \fi
+ \fi
+ %\relax
+ \topskipgap\topskip
+ \advance\topskipgap -\openstrutheight\relax
+ \ifdim\minimumstrutheight>\zeropoint
+ \ifdim\topskip<\minimumstrutheight
+ \topskip\minimumstrutheight\relax
+ \fi
+ \else
+ \ifdim\topskip<\strutheightfactor\openlineheight
+ \topskip\strutheightfactor\openlineheight\relax
+ \fi
+ \fi}
+
+\unexpanded\def\setmaxdepth
+ {\maxdepth\systemmaxdepthfactor\globalbodyfontsize}
+
+\let\normalbaselineskip \relax \newskip \normalbaselineskip % these got lost in the transition to mkiv due
+\let\normallineskip \relax \newskip \normallineskip % to auto-\normal* definitions and registers
+\let\normallineskiplimit\relax \newdimen\normallineskiplimit % being protected
+
+\unexpanded\def\normalbaselines
+ {\baselineskip \normalbaselineskip
+ \lineskip \normallineskip
+ \lineskiplimit\normallineskiplimit}
+
+\unexpanded\def\flexiblebaselines
+ {\baselineskip \normalbaselineskip
+ \lineskip 1\normallineskip \s!plus 1\s!fill
+ \lineskiplimit\normallineskiplimit}
+
+\unexpanded\def\setnormalbaselines
+ {\ifdim\normallineheight>\zeropoint
+ \lineheight\normallineheight
+ \fi
+ \openlineheight\spacingfactor\lineheight
+ \openstrutheight \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight % new
+ \else
+ \strutheightfactor\openlineheight
+ \fi
+ \openstrutdepth \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth % new
+ \else
+ \strutdepthfactor \openlineheight
+ \fi
+ \ifdim\dimexpr\minimumstrutdepth+\minimumstrutheight\relax>\zeropoint
+ \openlineheight\dimexpr\openstrutheight+\openstrutdepth\relax % new
+ \fi
+ \normalbaselineskip\openlineheight
+ \ifgridsnapping\else
+ \s!plus \m_spac_vertical_baseline_stretch_factor\openlineheight
+ \s!minus\m_spac_vertical_baseline_shrink_factor \openlineheight
+ \fi
+ \normallineskip\minimumlinedistance\relax % \onepoint\relax
+ \normallineskiplimit\zeropoint\relax
+ \normalbaselines}
+
+\unexpanded\def\spacing#1% vertical
+ {\ifgridsnapping
+ \let\spacingfactor\plusone
+ \else
+ \edef\spacingfactor{#1}%
+ \fi
+ \edef\systemtopskipfactor {\withoutpt\the\dimexpr#1\dimexpr\topskipfactor \points}%
+ \edef\systemmaxdepthfactor{\withoutpt\the\dimexpr#1\dimexpr\maxdepthfactor\points}%
+ \setnormalbaselines
+ \setstrut}
+
+% \unexpanded\def\forgetverticalstretch % \forgetspacing
+% {\spacing\plusone}
+
+\unexpanded\def\forgetverticalstretch
+ {\let\spacingfactor \plusone
+ \let\systemtopskipfactor \topskipfactor
+ \let\systemmaxdepthfactor\maxdepthfactor
+ \setnormalbaselines
+ \setstrut}
+
+\appendtoks
+ \forgetverticalstretch
+\to \everyforgetall % needed in otr
+
+%D Sometimes one needs to freeze the interlinespacing
+%D
+%D \starttyping
+%D \rm \saveinterlinespace .... {\ss \restoreinterlinespace .... \endgraf}
+%D \stoptyping
+
+\let\restoreinterlinespace\relax
+
+\unexpanded\def\saveinterlinespace
+ {\unexpanded\edef\restoreinterlinespace
+ {\lineheight \the\lineheight
+ \openstrutheight \the\openstrutheight
+ \openstrutdepth \the\openstrutdepth
+ \openlineheight \the\openlineheight
+ \normalbaselineskip \the\normalbaselineskip
+ \normallineskip \the\normallineskip
+ \normallineskiplimit\the\normallineskiplimit
+ \noexpand\def\noexpand\normallineheight{\the\dimexpr\normallineheight}%
+ \noexpand\normalbaselines}}
+
+%D This is the plain definition:
+%D
+%D \starttyping
+%D \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
+%D \stoptyping
+%D
+%D which could be:
+%D
+%D \starttyping
+%D \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
+%D \stoptyping
+%D
+%D But we do things differently.
+
+\newbox\strutbox
+
+\setbox\strutbox\hpack{\vrule\s!height8.5pt\s!depth3.5pt\s!width\zeropoint} % just a start
+
+\def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
+
+% \unexpanded\def\strut
+% {\relax
+% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox}
+
+\let\normalstrut\strut
+
+%D The double \type {\hbox} construction enables us to backtrack boxes.
+
+\let\strutht\undefined \newdimen\strutht
+\let\strutdp\undefined \newdimen\strutdp
+
+\unexpanded\def\setstrut
+ {\ifgridsnapping
+ \setstrutgridyes
+ \else
+ \setstrutgridnop
+ \fi}
+
+\unexpanded\def\setstrutgridyes
+ {\strutht\spacingfactor\dimexpr
+ \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight
+ \else
+ \strutheightfactor\dimexpr\normallineheight
+ \fi
+ \strutdp\dimexpr
+ \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth
+ \else
+ \normallineheight-\strutht
+ \fi
+ \dosetstrut}
+
+\unexpanded\def\setstrutgridnop
+ {\strutht\spacingfactor\dimexpr
+ \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight
+ \else
+ \strutheightfactor\dimexpr\normallineheight
+ \fi
+ \strutdp\spacingfactor\dimexpr
+ \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth
+ \else
+ \strutdepthfactor\dimexpr\normallineheight
+ \fi
+ \dosetstrut}
+
+\unexpanded\def\setcharstrut#1%
+ {\setbox\strutbox\hbox{#1}% no \hpack, in case we have smallcaps
+ \strutht\ht\strutbox
+ \strutdp\dp\strutbox
+ \dosetstrut}
+
+\unexpanded\def\settightstrut
+ {\setcharstrut{(}}
+
+\unexpanded\def\setfontstrut
+ {\setcharstrut{(gplQT}}
+
+\unexpanded\def\setcapstrut% could be M, but Q has descender
+ {\setcharstrut{Q}}
+
+%D Handy for math (used in mathml):
+
+\unexpanded\def\charhtstrut
+ {\begingroup
+ \setcharstrut{GJY}%
+ \vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht
+ \endgroup}
+
+\unexpanded\def\chardpstrut
+ {\begingroup
+ \setcharstrut{gjy}%
+ \vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint
+ \endgroup}
+
+%D Because of all the callbacks in mkiv, we avoid unnecessary boxes ... maybe use an
+%D attribute so that we can tag boxes that don't need a treatment; tests with using
+%D an attribute so far have shown that it's slower because testing the attribute
+%D takes time too.
+
+\unexpanded\def\dosetstrut
+ {\let\strut\normalstrut
+ \ifabsnum\dimexpr\strutht+\strutdp-\lineheight\relax<\plustwo
+ % compensate rounding error /- 1sp to avoid too many
+ % 1sp baselineskips in for instance verbatim
+ % \strutht\dimexpr\lineheight-\strutdp\relax
+ % better:
+ \strutdp\dimexpr\lineheight-\strutht\relax
+ \struttotal\lineheight
+ \else
+ \struttotal\dimexpr\strutht+\strutdp\relax
+ \fi
+ \edef\strutheight{\the\strutht}%
+ \edef\strutdepth {\the\strutdp}%
+ \ifdim\strutwidth=\zeropoint
+ \spac_struts_set_hide
+ \else
+ \spac_struts_set_vide
+ \fi}
+
+\def\spac_struts_set_hide
+ {\setbox\strutbox\hpack
+ {\vrule
+ \s!width \zeropoint
+ \s!height\strutht
+ \s!depth \strutdp}}
+
+\newconstant\c_strut_visual_mode
+
+\def\spac_struts_set_vide
+ {\setbox\strutbox\hpack % at some time this extra wrapping was needed
+ {\spac_struts_vide_hbox to \zeropoint
+ {\ifcase\c_strut_visual_mode
+ \spac_struts_black
+ \or
+ \spac_struts_color
+ \else
+ \spac_struts_black
+ \fi}}}
+
+\def\spac_struts_black
+ {\vrule
+ \s!width \strutwidth
+ \s!height\strutht
+ \s!depth \strutdp
+ \hss}
+
+\def\spac_struts_color
+ {\hss % new, will be option
+ \scratchwidth.1\struthtdp
+ \begingroup
+ \directcolor[f:b:t]%
+ \vrule
+ \s!width \scratchwidth
+ \s!height\strutht
+ \s!depth \strutdp
+ \kern-\scratchwidth
+ \vrule
+ \s!width \scratchwidth
+ \s!height\zeropoint
+ \s!depth \strutdp
+ \endgroup
+ \kern-.625\scratchwidth
+ \vrule
+ \s!width .25\scratchwidth
+ \s!height\strutht
+ \s!depth \strutdp
+ \hss}
+
+\let\spac_struts_vide_hbox\hbox % overloaded in trac-vis.mkiv
+
+%D The dimen \type {\struttotal} holds the exact size of the strut; occasionally a
+%D one scaled point difference can show up with the lineheight. This is more
+%D efficient (less callbacks):
+
+\newbox\b_spac_struts_empty \setbox\b_spac_struts_empty\emptyhbox
+
+\def\spac_struts_set_hide
+ {\setbox\strutbox\copy\b_spac_struts_empty
+ \ht\strutbox\strutht
+ \dp\strutbox\strutdp}
+
+\unexpanded\def\strut % still callbacks for \hbox{\strut}
+ {\relax
+ \dontleavehmode
+ \copy\strutbox}
+
+% \unexpanded\def\strut % slightly faster
+% {\relax
+% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox}
+
+\let\normalstrut\strut
+
+\unexpanded\def\halfstrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\dimexpr\strutht/\plustwo\relax
+ \dp\scratchbox\dimexpr\strutdp/\plustwo\relax
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\quarterstrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\dimexpr\strutht/\plusfour\relax
+ \dp\scratchbox\dimexpr\strutdp/\plusfour\relax
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\depthstrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\dimexpr\strutht-\struthtdp/\plustwo\relax % assumes that ht > lineheight/2
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\halflinestrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\dimexpr\strutht-.5\strutht-.5\strutdp\relax
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\noheightstrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\zeropoint
+ \box\scratchbox
+ \endgroup}
+
+%D Sometimes a capstrut comes in handy
+%D
+%D \starttabulate[|Tl|l|l|]
+%D \NC yes \NC normal strut \NC {\showstruts\setupstrut[yes]\strut} \NC \NR
+%D \NC no \NC no strut \NC {\showstruts\setupstrut[no]\strut} \NC \NR
+%D \NC kap \NC a capital strut (i.e. Q) \NC {\showstruts\setupstrut[cap]\strut} \NC \NR
+%D \NC A B \unknown \NC a character strut (e.g. A) \NC {\showstruts\setupstrut[A]\strut} \NC \NR
+%D \NC \NC a normal strut \NC {\showstruts\setupstrut\strut} \NC \NR
+%D \stoptabulate
+%D
+%D Beware: using an unknown value results in char struts.
+
+\installcorenamespace{struts}
+
+\unexpanded\def\setupstrut
+ {\dosingleempty\spac_struts_setup}
+
+\def\spac_struts_setup[#1]%
+ {\edef\m_strut{#1}%
+ \ifcsname\??struts\m_strut\endcsname
+ \lastnamedcs
+ \else
+ \setcharstrut\m_strut
+ \fi}
+
+\unexpanded\def\synchronizestrut#1% no [] parsing, faster for internal
+ {\edef\m_strut{#1}%
+ \ifcsname\??struts\m_strut\endcsname
+ \lastnamedcs
+ \else
+ \setcharstrut\m_strut
+ \fi}
+
+\unexpanded\def\dosynchronizestrut#1% no [] parsing, faster for internal
+ {\ifcsname\??struts#1\endcsname
+ \lastnamedcs
+ \else
+ \setcharstrut{#1}%
+ \fi}
+
+\unexpanded\def\showstruts % adapts .. is wrong
+ {\c_strut_visual_mode\zerocount
+ \setteststrut
+ \settestcrlf}
+
+\unexpanded\def\showcolorstruts % adapts .. is wrong
+ {\c_strut_visual_mode\plusone
+ \setteststrut
+ \settestcrlf}
+
+\unexpanded\def\setteststrut
+ {\def\strutwidth{.8pt}%
+ \setstrut}
+
+\unexpanded\def\dontshowstruts
+ {\unsetteststrut
+ \settestcrlf}
+
+\unexpanded\def\unsetteststrut
+ {\let\strutwidth\zeropoint
+ \setstrut}
+
+\def\autostrutfactor{1.1}
+
+\unexpanded\def\setautostrut
+ {\begingroup
+ \setbox\scratchbox\copy\strutbox
+ \setstrut
+ \ifdim\strutht>\autostrutfactor\ht\scratchbox
+ \endgroup \setstrut
+ \orelse\ifdim\strutdp>\autostrutfactor\dp\scratchbox
+ \endgroup \setstrut
+ \else
+ \endgroup
+ \fi}
+
+\newbox\nostrutbox \setbox\nostrutbox\emptyhbox
+
+\newtoks\everysetnostrut
+
+\unexpanded\def\setnostrut
+ {\the\everysetnostrut}
+
+\appendtoks
+ \setbox\strutbox\copy\nostrutbox
+ \let\strut\empty
+ \let\endstrut\empty
+ \let\begstrut\empty
+\to \everysetnostrut
+
+%D When enabled, sigstruts will remove themselves if nothing goes inbetween. For
+%D practical reasons we define some boundary characters here.
+
+\unexpanded\def\leftboundary {\protrusionboundary\plusone}
+\unexpanded\def\rightboundary {\protrusionboundary\plustwo}
+\unexpanded\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals
+
+\newsignal\strutsignal \setfalse\sigstruts
+
+\unexpanded\def\begstrut
+ {\relax\ifcase\strutht
+ % \ignorespaces % maybe
+ \else
+ \spac_struts_beg
+ \fi}
+
+\def\spac_struts_beg
+ {\ifconditional\sigstruts
+ \spac_struts_beg_signal
+ \else
+ \spac_struts_beg_normal
+ \fi
+ \ignorespaces}
+
+\def\spac_struts_beg_signal
+ {\noindent\horizontalstrut
+ \penalty\plustenthousand
+ \hskip-\strutsignal
+ \hskip\strutsignal}
+
+\def\spac_struts_beg_normal
+ {\boundary\plusone
+ \strut
+ %\boundary\plusone
+ \penalty\plustenthousand
+ %\boundary\plusone
+ \hskip\zeropoint}
+
+\unexpanded\def\endstrut
+ {\relax\ifhmode
+ \ifcase\strutht
+ % \removeunwantedspaces % maybe
+ \else
+ \spac_struts_end
+ \fi
+ \fi}
+
+\def\spac_struts_end
+ {\ifconditional\sigstruts
+ \spac_struts_end_signal
+ \else
+ \spac_struts_end_normal
+ \fi}
+
+\def\spac_struts_end_signal
+ {\ifdim\lastskip=\strutsignal
+ \unskip
+ \unskip
+ \unpenalty
+ \setbox\scratchbox\lastbox
+ \else
+ \penalty\plustenthousand
+ \hskip\zeropoint
+ \strut
+ \fi}
+
+\def\spac_struts_end_normal
+ {\removeunwantedspaces
+ \penalty\plustenthousand
+ %\boundary\plustwo
+ \hskip\zeropoint
+ %\boundary\plustwo
+ \strut
+ \boundary\plustwo}
+
+% unsave:
+%
+% \def\pseudostrut
+% {\bgroup
+% \setnostrut
+% \normalstrut
+% \egroup}
+%
+% try:
+%
+% \startchemie
+% \chemie[ONE,Z0,SB15,MOV1,SB15,Z0][C,C]
+% \stopchemie
+%
+% so:
+
+\unexpanded\def\pseudostrut
+ {\noindent} % better: \dontleavehmode
+
+\let\pseudobegstrut\pseudostrut
+\let\pseudoendstrut\removeunwantedspaces
+
+\unexpanded\def\resetteststrut
+ {\def\strutwidth{\zeropoint}% no let
+ \setstrut}
+
+\ifdefined\setfontparameters \else
+ \def\setfontparameters{\the\everybodyfont}
+\fi
+
+%D Keyword based strutting:
+
+\letvalue{\??struts\v!yes }\setstrut
+\letvalue{\??struts\v!auto }\setautostrut
+\letvalue{\??struts\v!no }\setnostrut
+\letvalue{\??struts\v!cap }\setcapstrut
+\letvalue{\??struts\v!fit }\setfontstrut
+\letvalue{\??struts\v!line }\setstrut
+\letvalue{\??struts\s!default}\setstrut
+\letvalue{\??struts\empty }\setstrut
+
+%D Handy:
+
+\def\baselinedistance{\the\lineheight}
+
+%D We need \type {\normaloffinterlineskip} because the new definition contains an
+%D assignment, and |<|don't ask me why|>| this assignment gives troubles in for
+%D instance the visual debugger.
+
+\unexpanded\def\offinterlineskip
+ {\baselineskip-\thousandpoint
+ \lineskip \zeropoint
+ \lineskiplimit\maxdimen
+ % We also need this here now; thanks to taco for figuring that out!
+ \def\minimumlinedistance{\zeropoint}}
+
+\unexpanded\def\nointerlineskip
+ {\prevdepth-\thousandpoint}
+
+\let\normaloffinterlineskip\offinterlineskip % knuth's original
+
+%D This is tricky. The prevdepth value is still set to the last one even if there is
+%D nothing on the page. The same is true for prevgraf, which doesn't resemble the
+%D value on the current page.
+%D
+%D So, here we kick in a checker but it has to happen after the output group and it
+%D only has to be done once (output can trigger itself!).
+%D
+%D However, prevgraf is somehow bound to hangindent so we can get very nasty side
+%D effects. So, in tne end we use our own variable!
+
+\ifdefined\getnofpreviouslines
+ % defined public at the lua end
+\else
+ \let\getnofpreviouslines\!!zerocount
+\fi
+
+\unexpanded\def\page_otr_synchronize_page_yes
+ {\aftergroup\page_otr_synchronize_page_indeed
+ \glet\page_otr_synchronize_page\relax}
+
+% \unexpanded\def\page_otr_synchronize_page_indeed
+% {\clf_synchronizepage
+% \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes}
+%
+% This has to become an otr method: \s!page_otr_command_synchonize_page
+
+\unexpanded\def\page_otr_synchronize_page_indeed
+ {\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi
+ \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes}
+
+\let\page_otr_synchronize_page\page_otr_synchronize_page_yes
+
+\appendtoks
+ \page_otr_synchronize_page
+\to \everyaftershipout
+
+%D My own one:
+
+\unexpanded\def\spac_helpers_push_interlineskip_yes
+ {\edef\oninterlineskip
+ {\baselineskip \the\baselineskip
+ \lineskip \the\lineskip
+ \lineskiplimit\the\lineskiplimit
+ \noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}%
+ \let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed
+
+\unexpanded\def\spac_helpers_push_interlineskip_nop
+ {\let\oninterlineskip\setnormalbaselines}
+
+\unexpanded\def\offinterlineskip
+ {\ifdim\baselineskip>\zeropoint
+ \spac_helpers_push_interlineskip_yes
+ \else
+ \spac_helpers_push_interlineskip_nop
+ \fi
+ \normaloffinterlineskip}
+
+\let\oninterlineskip\relax
+
+\unexpanded\def\leaveoutervmode
+ {\ifvmode\ifinner\else
+ \leavevmode
+ \fi\fi}
+
+\unexpanded\def\resetpenalties#1%
+ {\ifdefined#1%
+ #1\minusone
+ \fi}
+
+\unexpanded\def\setpenalties#1#2#3%
+ {\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text
+ #1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax
+ \fi}
+
+%D \macros
+%D {keeplinestogether}
+%D
+%D Dirty hack, needed in margin content that can run of a page.
+
+% just before margintexts ... will eventually be done differently in mkiv using
+% attributes
+
+\newcount\c_spac_keep_lines_together
+\let\restoreinterlinepenalty\relax
+
+\unexpanded\def\spac_penalties_restore
+ {\glet\restoreinterlinepenalty\relax
+ \global\resetpenalties\interlinepenalties
+ \global\c_spac_keep_lines_together\zerocount}
+
+\unexpanded\def\keeplinestogether#1%
+ {\ifnum#1>\c_spac_keep_lines_together
+ \global\c_spac_keep_lines_together#1%
+ \global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand
+ \glet\restoreinterlinepenalty\spac_penalties_restore
+ \fi}
+
+\def\defaultdisplaywidowpenalty {50}
+\def\defaultwidowpenalty {2000} % was: 1000
+\def\defaultclubpenalty {2000} % was: 800
+\def\defaultbrokenpenalty {100}
+\def\defaultdoublehyphendemerits {10000}
+\def\defaultfinalhyphendemerits {5000}
+\def\defaultadjdemerits {10000}
+
+\def\defaultgriddisplaywidowpenalty {0}
+\def\defaultgridwidowpenalty {0}
+\def\defaultgridclubpenalty {0}
+\def\defaultgridbrokenpenalty {0}
+\def\defaultgriddoublehyphendemerits{10000} % always was so
+\def\defaultgridfinalhyphendemerits {5000} % always was so
+\def\defaultgridadjdemerits {10000} % always was so
+
+\unexpanded\def\nopenalties
+ {\widowpenalty \zerocount
+ \clubpenalty \zerocount
+ \brokenpenalty \zerocount
+ \doublehyphendemerits\zerocount
+ \finalhyphendemerits \zerocount
+ \adjdemerits \zerocount}
+
+\unexpanded\def\setdefaultpenalties
+ {\directsetup{\systemsetupsprefix\s!default}}
+
+\startsetups [\systemsetupsprefix\s!reset]
+ \resetpenalties\widowpenalties
+ \resetpenalties\clubpenalties
+ \resetpenalties\interlinepenalties
+\stopsetups
+
+%D We use \directsetup because it's faster and we know there is no csl:
+
+\startsetups [\systemsetupsprefix\s!default]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \widowpenalty \defaultwidowpenalty
+ \clubpenalty \defaultclubpenalty
+ \displaywidowpenalty \defaultdisplaywidowpenalty
+ \brokenpenalty \defaultbrokenpenalty
+ \doublehyphendemerits\defaultdoublehyphendemerits
+ \finalhyphendemerits \defaultfinalhyphendemerits
+ \adjdemerits \defaultadjdemerits
+
+\stopsetups
+
+\startsetups [\v!grid] [\systemsetupsprefix\s!default]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \widowpenalty \defaultgridwidowpenalty
+ \clubpenalty \defaultgridclubpenalty
+ \displaywidowpenalty \defaultgriddisplaywidowpenalty
+ \brokenpenalty \defaultgridbrokenpenalty
+ \doublehyphendemerits\defaultgriddoublehyphendemerits
+ \finalhyphendemerits \defaultgridfinalhyphendemerits
+ \adjdemerits \defaultgridadjdemerits
+
+\stopsetups
+
+%D As an illustration:
+
+\startsetups [\systemsetupsprefix\v!strict]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \setpenalties \widowpenalties \plustwo \maxdimen
+ \setpenalties \clubpenalties \plustwo \maxdimen
+ \brokenpenalty \maxdimen
+ \doublehyphendemerits \defaultdoublehyphendemerits
+ \finalhyphendemerits \defaultfinalhyphendemerits
+ \adjdemerits \defaultadjdemerits
+
+\stopsetups
+
+\setdefaultpenalties % will happen later in \setuplayout
+
+%D To be checked:
+
+\newbox\b_spac_struts_saved
+
+\unexpanded\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox}
+\unexpanded\def\savedstrut{\copy \b_spac_struts_saved}
+
+%D Good old blank redone:
+
+%definesystemattribute[kernchars] [public]
+\definesystemattribute[skipcategory] [public]
+\definesystemattribute[skippenalty] [public]
+\definesystemattribute[skiporder] [public]
+\definesystemattribute[snapmethod] [public]
+\definesystemattribute[snapvbox] [public]
+%definesystemattribute[snapcategory] [public]
+
+% TODO: NAMED SNAPPERS
+
+\installcorenamespace{gridsnappers}
+\installcorenamespace{gridsnapperattributes}
+\installcorenamespace{gridsnappersets}
+
+\newskip \bodyfontlineheight
+\newdimen \bodyfontstrutheight
+\newdimen \bodyfontstrutdepth
+
+\newskip \globalbodyfontlineheight % why a skip
+\newdimen \globalbodyfontstrutheight
+\newdimen \globalbodyfontstrutdepth
+
+\def\snappedvboxattribute{\ifgridsnapping attr \snapvboxattribute \attribute\snapmethodattribute\fi}
+\def\setlocalgridsnapping{\ifgridsnapping \attribute \snapvboxattribute \attribute\snapmethodattribute\fi}
+
+\def\spac_grids_set_local_snapping#1%
+ {\ifgridsnapping
+ \doifsomething{#1}%
+ {\spac_grids_snap_value_set{#1}%
+ \attribute \snapvboxattribute \attribute\snapmethodattribute}%
+ \fi}
+
+\def\spac_grids_expand_snapper#1%
+ {\edef\m_spac_snapper
+ {\ifx\m_spac_snapper\empty\else\m_spac_snapper,\fi
+ \ifcsname\??gridsnappersets#1\endcsname
+ \lastnamedcs\else#1%
+ \fi}}
+
+\unexpanded\def\installsnapvalues#1#2%
+ {\let\m_spac_snapper\empty
+ \rawprocesscommacommand[#2]\spac_grids_expand_snapper
+ \edef\currentsnapper{#1:\m_spac_snapper}%
+ \ifcsname\??gridsnapperattributes\currentsnapper\endcsname
+ \scratchcounter\lastnamedcs % already defined
+ \else
+ \scratchcounter\clf_definesnapmethod{#1}{\m_spac_snapper}%
+ \setevalue{\??gridsnapperattributes\currentsnapper}{\the\scratchcounter}%
+ \fi
+ \setevalue{\??gridsnappers#1}{\attribute\snapmethodattribute\the\scratchcounter\relax}%
+ \letvalue{\??gridsnappersets#1}\m_spac_snapper}
+
+\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals
+
+\unexpanded\def\usegridparameter#1% no checking here
+ {\edef\m_spac_grid_asked{#1\c!grid}%
+ \ifx\m_spac_grid_asked\empty
+ \attribute \snapvboxattribute\attributeunsetvalue
+ \else
+ \spac_grids_snap_value_set\m_spac_grid_asked
+ \attribute \snapvboxattribute\attribute\snapmethodattribute
+ \fi}
+
+\unexpanded\def\definegridsnapping
+ {\dodoubleargument\spac_grids_define}
+
+\def\spac_grids_define[#1][#2]%
+ {\installsnapvalues{#1}{#2}}
+
+\edef\spac_grids_snap_value_reset
+ {%\gridsnappingfalse
+ \attribute\snapmethodattribute\attributeunsetvalue}
+
+\def\spac_grids_snap_value_set#1%
+ {%\gridsnappingtrue
+ \begincsname\??gridsnappers#1\endcsname}
+
+% maybe:
+%
+% \def\spac_grids_snap_value_set#1%
+% {%\gridsnappingtrue
+% \ifcsname\??gridsnappers#1\endcsname
+% \lastnamedcs
+% \else
+% \definegridsnapping[#1][#1]%
+% \begincsname\??gridsnappers#1\endcsname
+% \fi}
+
+\def\spac_grids_snap_value_auto#1%
+ {\ifcsname\??gridsnappers#1\endcsname
+ \lastnamedcs
+ \else
+ \installsnapvalues\s!dummy{#1}%
+ \csname\??gridsnappers\s!dummy\endcsname
+ \fi}
+
+% \installsnapvalues{loose} {\v!maxdepth:0.8,\v!maxheight:0.8,\v!strut}
+% \installsnapvalues{normal}{\v!maxdepth:1.0,\v!maxheight:1.0,\v!strut}
+% \installsnapvalues{tight} {\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut}
+
+% none don't enlarge
+% halfline enlarge by halfline/halfline
+% line enlarge by line/line
+% strut enlarge by ht/dp (default)
+% first align to top line
+% last align to bottom line
+% mindepth round depth down
+% maxdepth round depth up
+% minheight round height down
+% maxheight round height up
+% local use local interline space
+% offset:-3tp vertical shift within box
+% bottom:lines
+% top:lines
+% box centers a box rounded upwards (box:.5 -> tolerance)
+% min centers a box rounded downwards
+% max centers a box rounded upwards
+
+%D We're not downward compatible with \MKII ! Not yet in interface file:
+
+\definegridsnapping[\v!normal] [\v!maxheight,\v!maxdepth,\v!strut]
+\definegridsnapping[\v!standard] [\v!maxheight,\v!maxdepth,\v!strut]
+\definegridsnapping[\v!yes] [\v!maxheight,\v!maxdepth,\v!strut]
+
+\definegridsnapping[\v!strict] [\v!maxdepth:0.8,\v!maxheight:0.8,\v!strut]
+\definegridsnapping[\v!tolerant] [\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut]
+\definegridsnapping[\v!verytolerant] [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut]
+
+\definegridsnapping[\v!tolerant:10] [\v!maxdepth:1.1,\v!maxheight:1.1,\v!strut] % 10 pct tolerance
+\definegridsnapping[\v!tolerant:20] [\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut] % 20 pct tolerance
+\definegridsnapping[\v!tolerant:30] [\v!maxdepth:1.3,\v!maxheight:1.3,\v!strut] % 30 pct tolerance
+\definegridsnapping[\v!tolerant:40] [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut] % 40 pct tolerance
+
+\definegridsnapping[\v!top] [\v!minheight,\v!maxdepth,\v!strut]
+\definegridsnapping[\v!bottom] [\v!maxheight,\v!mindepth,\v!strut]
+\definegridsnapping[\v!both] [\v!minheight,\v!mindepth,\v!strut]
+
+\definegridsnapping[\v!broad] [\v!maxheight,\v!maxdepth,\v!strut,0.8] % maybe 0.85
+\definegridsnapping[\v!fit] [\v!maxheight,\v!maxdepth,\v!strut,1.2] % tight 0.15
+
+\definegridsnapping[\v!first] [\v!first]
+\definegridsnapping[\v!last] [\v!last]
+\definegridsnapping[\v!high] [\v!minheight,\v!maxdepth,\v!none]
+\definegridsnapping[\v!one] [\v!minheight,\v!mindepth]
+\definegridsnapping[\v!low] [\v!maxheight,\v!mindepth,\v!none]
+\definegridsnapping[\v!none] [\v!none]
+\definegridsnapping[\v!line] [\v!line]
+\definegridsnapping[\v!strut] [\v!strut]
+\definegridsnapping[\v!box] [\v!box]
+\definegridsnapping[\v!min] [\v!min]
+\definegridsnapping[\v!max] [\v!max]
+
+\definegridsnapping[\v!middle] [\v!maxheight,\v!maxdepth] % used in placement
+
+\definegridsnapping[\v!math] [\v!maxdepth:1.05,\v!maxheight:1.05,\v!strut] % experimental, maybe 1.1
+\definegridsnapping[\v!math:\v!line] [\v!math,\v!line,\v!split]
+\definegridsnapping[\v!math:\v!halfline] [\v!math,\v!halfline,\v!split]
+\definegridsnapping[\v!math:-\v!line] [\v!math,-\v!line,\v!split]
+\definegridsnapping[\v!math:-\v!halfline][\v!math,-\v!halfline,\v!split]
+
+\unexpanded\def\synchronizelocallinespecs
+ {\bodyfontlineheight \normallineheight
+ \bodyfontstrutheight\strutht
+ \bodyfontstrutdepth \strutdp}
+
+\unexpanded\def\synchronizegloballinespecs
+ {\global\globalbodyfontlineheight \normallineheight
+ \global\globalbodyfontstrutheight\strutht
+ \global\globalbodyfontstrutdepth \strutdp}
+
+\appendtoks
+ \synchronizegloballinespecs
+ \synchronizelocallinespecs
+\to \everysetupglobalinterlinespace
+
+\appendtoks
+ \synchronizelocallinespecs
+\to \everysetuplocalinterlinespace
+
+%D We still have to synchronize these:
+
+\unexpanded\def\synchronizeskipamounts
+ {\bigskipamount
+ \skipfactor\baselineskip
+ \s!plus\skipgluefactor\baselineskip
+ \s!minus\skipgluefactor\baselineskip
+ \relax
+ \medskipamount \bigskipamount \divide\medskipamount \plustwo
+ \smallskipamount\bigskipamount \divide\smallskipamount\plusfour}
+
+%D Snapping.
+
+\newif\ifgridsnapping
+
+%unexpanded\def\moveongrid {\dosingleempty\spac_grids_move_on}
+\unexpanded\def\snaptogrid {\dosingleempty\spac_grids_snap_to}
+\unexpanded\def\placeongrid{\dosingleempty\spac_grids_place_on}
+
+\unexpanded\def\startgridsnapping
+ {\dosingleempty\spac_grids_start_snapping}
+
+\unexpanded\def\spac_grids_start_snapping[#1]%
+ {\snaptogrid[#1]\vbox\bgroup}
+
+\unexpanded\def\stopgridsnapping
+ {\egroup}
+
+% \def\spac_grids_move_on[#1]%
+% {[obsolete]} % gone, unless we set an attribute
+
+\def\spac_grids_place_on[#1]%
+ {\snaptogrid[#1]\vbox} % mark as done
+
+\def\spac_grids_snap_to[#1]% list or predefined
+ {\ifgridsnapping
+ \expandafter\spac_grids_snap_to_indeed
+ \else
+ \expandafter\gobbleoneargument
+ \fi{#1}}
+
+\def\spac_grids_snap_to_indeed#1%
+ {\bgroup
+ \spac_grids_snap_value_reset
+ \dowithnextbox{\spac_grids_snap_to_finish{#1}}}
+
+% eventually there will always be a line snap
+
+\def\spac_grids_snap_to_finish#1%
+ {\ifvbox\nextbox % this will go away
+ \clf_vspacingcollapse\nextbox\relax % isn't that already done?
+ \fi
+ \doifelsenothing{#1}{\spac_grids_snap_value_set\v!normal}{\spac_grids_snap_value_set{#1}}%
+ \clf_vspacingsnap\nextbox\attribute\snapmethodattribute\relax
+ \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% no pack (?), we snap
+ \egroup}
+
+\def\spac_grids_check_nop
+ {\gridsnappingfalse
+ \resetsystemmode\v!grid
+ \spac_grids_snap_value_reset}
+
+\def\spac_grids_check_yes
+ {\gridsnappingtrue
+ \setsystemmode\v!grid
+ \spac_grids_snap_value_set\askedgridmode}
+
+\unexpanded\def\synchronizegridsnapping
+ {\edef\askedgridmode{\layoutparameter\c!grid}%
+ \ifx\askedgridmode\v!no % official
+ \spac_grids_check_nop
+ \orelse\ifx\askedgridmode\v!off % for taco and luigi
+ \spac_grids_check_nop
+ \orelse\ifx\askedgridmode\empty % to be sure
+ \spac_grids_check_nop
+ \else
+ \spac_grids_check_yes
+ \fi}
+
+\unexpanded\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing)
+ {\setlayoutparameter\c!grid{#1}\synchronizegridsnapping}
+
+\unexpanded\def\checkgridmethod#1%
+ {\edef\p_grid{#1}%
+ \ifx\p_grid\empty
+ \let\checkedgridmethod\empty
+ \let\checkedgridscope \v!local
+ \else
+ \splitatcolon\p_grid\checkedgridscope\checkedgridmethod
+ \ifx\checkedgridmethod\empty
+ \ifx\checkedgridscope\v!local\orelse\ifx\checkedgridscope\v!global\else
+ \let\checkedgridmethod\checkedgridscope
+ \let\checkedgridscope \v!local
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\applygridmethod#1#2#3% content localsettings (used in head rendering)
+ {\checkgridmethod{#1}%
+ \ifx\checkedgridscope\v!global
+ \ifx\checkedgridmethod\empty \else
+ % we assume that the call is grouped because grouping here has the side
+ % effect that the eventually constructed line will get the value outside
+ % the group
+ %
+ % overkill: \setupgridsnapping[\checkedgridmethod]%
+ % maybe : \spac_grids_snap_value_auto\checkedgridmethod
+ \spac_grids_snap_value_set\checkedgridmethod
+ \fi
+ \hbox{#3}%
+ \else
+ % the extra hbox will trigger the global snapper on top of the local and
+ % we really need that in this case (compatibility etc etc) so here we don't
+ % het an already done hit (otherwise we would not snap)
+ \hbox\bgroup
+ \ifx\checkedgridmethod\empty\orelse\ifconditional\headisdisplay
+ #2%
+ \fi
+ \snaptogrid[\checkedgridmethod]\hbox{#3}%
+ \egroup
+ \fi}
+
+\unexpanded\gdef\page_layouts_calculate_overshoot
+ {\ifgridsnapping\ifcase\layoutlines
+ \getnoflines\textheight
+ \textovershoot\dimexpr\noflines\globalbodyfontlineheight-\textheight\relax
+ \fi\fi}
+
+\unexpanded\def\page_layouts_report_overshoot
+ {\page_layouts_calculate_overshoot
+ \ifdim\textovershoot>\zeropoint
+ \writestatus\m!layouts{gridmode,\space
+ noflines: \the\noflines,\space
+ textheight: \the\textheight,\space
+ textovershoot: \the\textovershoot\space
+ (maybe set number of lines instead)%
+ }%
+ \fi
+ \glet\page_layouts_report_overshoot\page_layouts_calculate_overshoot}
+
+\appendtoks
+ \page_layouts_report_overshoot
+\to \everybeforepagebody
+
+%D Visualization:
+
+\definepalet
+ [grid]
+ [ one=red,
+ two=green,
+ three=blue,
+ four=gray]
+
+\unexpanded\def\setgridtracebox#1[#2]% % maybe reverse the order
+ {\setbox\nextbox#1%
+ {\hbox
+ {\hbox to \zeropoint
+ {\setlayoutcomponentattribute{\v!grid:\v!test}%
+ \color[grid:#2]{\ruledhbox \layoutcomponentboxattribute {\fakebox\nextbox}}%
+ \hss}%
+ \flushnextbox}}}
+
+\setnewconstant\gridboxlinenomode\plusone % 0:nothing 1:all 2:lines 3:frame 4:l/r
+\setnewconstant\gridboxlinemode \plusone
+
+\unexpanded\def\gridboxvbox
+ {\ifcase\gridboxlinemode
+ \vpack
+ \or
+ \ruledvpack
+ \or
+ \vpack
+ \or
+ \ruledvpack
+ \else
+ \ruledvpack
+ \fi}
+
+\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
+
+\unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
+ {\setbox#1\gridboxvbox to #3 % given size
+ {\forgetall
+ \resetvisualizers
+ \resetteststrut
+ \offinterlineskip
+ \hsize#2%
+ \ifcase\gridboxlinenomode\or\or\or
+ \gridboxlinenomode\doifoddpageelse\plusone\plustwo % 3: outer
+ \or
+ \gridboxlinenomode\doifoddpageelse\plustwo\plusone % 4: inner
+ \fi
+ \topskipcorrection
+ \gridboxvbox % calculated size
+ {\getrawnoflines{#3}% \getnoflines{#3}%
+ \scratchdimen\dimexpr#2+\lineheight\relax
+ \dorecurse\noflines
+ {\strut
+ \hskip-.5\lineheight\relax
+ \ifcase\gridboxlinenomode\or
+ \rlap
+ {\hskip\dimexpr.2\bodyfontsize+\scratchdimen\relax
+ \infofont\hbox to \emwidth{\hss\recurselevel}}%
+ \or
+ \llap
+ {\infofont\hbox to \emwidth{\hss\recurselevel}%
+ \hskip.2\bodyfontsize}%
+ \fi
+ \vrule
+ \s!height \gridboxwidth
+ \s!depth \gridboxwidth
+ \s!width \scratchdimen
+ \par}}
+ \vfill}}
+
+%D This has become obsolete:
+
+\def\fuzzysnappedbox#1#2% \box<n> \unvbox<n>
+ {#1#2}
+
+\def\moveboxontogrid#1#2#3% will become obsolete, but it needs checking
+ {}
+
+%D Helper:
+
+\unexpanded\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap
+ {\doifelse{#2}\v!line
+ {#1\ifgridsnapping
+ \bodyfontlineheight
+ \else
+ \openlineheight
+ \fi}
+ {\ifgridsnapping
+ \assigndimension{#2}{#1}{.25\bodyfontlineheight}{.5\bodyfontlineheight}\bodyfontlineheight
+ \else
+ \assigndimension{#2}{#1}\smallskipamount\medskipamount\bigskipamount
+ \fi}%
+ \relax}
+
+% \start \dosetstretch{.25em} \setuptolerance[tolerant,stretch] \input tufte \endgraf \stop
+% \start \dosetstretch{.5em} effe flink doorfietsen \stop
+
+% experimental code, not yet interfaced:
+
+% category:
+%
+% 0 == discard discard
+% 1 == only if larger largest
+% 2 == force even if smaller force
+% 3 == only take penalty component penalty
+% 4 == add to existing skip add
+% 5 == disable (ignore following) disable
+% 6 == kill whitespace nowhite
+% 7 == discard previous back
+% 10 == no topskip
+%
+% penalty: larger wins
+% order: larger wins
+% category:2,order:5,penalty:10000,skip:value|kw
+%
+% \defineblankmethod [\v!joinedup] {\ifvmode\nointerlineskip\fi}
+
+% todo, in grid mode: builders.vspacing.fixed = false
+%
+% \ifgridsnapping will go
+
+\installcorenamespace{vspacingamount}
+
+\unexpanded\def\definevspacingamount
+ {\dotripleempty\spac_vspacing_define_amount}
+
+\def\spac_vspacing_define_amount[#1][#2][#3]% can be combined
+ {\ifthirdargument
+ \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}%
+ \orelse\ifsecondargument
+ \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}%
+ \else
+ \setvalue{\??vspacingamount#1}{\lineheight}%
+ \fi
+ \clf_vspacingsetamount{#1}}
+
+\def\spac_vspacing_no_topskip % use grouped
+ {\attribute\skipcategoryattribute\plusten}
+
+% \installcorenamespace{vspacingamountnormal}
+% \installcorenamespace{vspacingamountgrid}
+
+% \def\spac_vspacing_define_amount[#1][#2][#3]% can be combined
+% {\ifcsname n>#1\endcsname\else
+% \expandafter\newtoks\csname n>#1\endcsname
+% \expandafter\newtoks\csname g>#1\endcsname
+% \fi
+% \csname n>#1\endcsname{#2}%
+% \csname g>#1\endcsname{#3}%
+% \clf_vspacingsetamount{#1}}
+
+\unexpanded\def\definevspacing
+ {\dodoubleempty\spac_vspacing_define}
+
+\def\spac_vspacing_define[#1][#2]%
+ {\clf_vspacingdefine{#1}{#2}}
+
+%D The injector code (generated at the \LUA\ end):
+
+\newtoks\everybeforeblankhandling
+\newtoks\everyafterblankhandling
+
+\newconditional\c_space_vspacing_done
+\newconditional\c_space_vspacing_fixed
+\newconditional\c_space_ignore_parskip
+
+\appendtoks
+ \s_spac_vspacing_temp\zeropoint
+ \attribute\skipcategoryattribute\plusone
+ \attribute\skippenaltyattribute \attributeunsetvalue
+ \attribute\skiporderattribute \attributeunsetvalue
+ \ifgridsnapping
+ \settrue\c_space_vspacing_fixed
+ \else
+ \setfalse\c_space_vspacing_fixed
+ \fi
+\to \everybeforeblankhandling
+
+\appendtoks
+ \s_spac_vspacing_temp\plusone\s_spac_vspacing_temp
+ \ifconditional\c_space_vspacing_fixed \else
+ \s!plus \skipgluefactor\s_spac_vspacing_temp
+ \s!minus\skipgluefactor\s_spac_vspacing_temp
+ \fi
+ \relax
+\to \everyafterblankhandling
+
+\unexpanded\def\setblankpacked
+ {\settrue\c_space_ignore_parskip}
+
+\unexpanded\def\setblankcategory#1%
+ {\settrue\c_space_vspacing_done
+ \attribute\skipcategoryattribute#1\relax}
+
+\unexpanded\def\setblankorder#1%
+ {\attribute\skiporderattribute#1\relax}
+
+\unexpanded\def\fixedblankskip
+ {\settrue\c_space_vspacing_fixed}
+
+\unexpanded\def\flexibleblankskip
+ {\setfalse\c_space_vspacing_fixed}
+
+% \unexpanded\def\addblankskip#1#2#3%
+% {\settrue\c_space_vspacing_done
+% \advance\s_spac_vspacing_temp#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax}
+
+\unexpanded\def\setblankpenalty#1%
+ {\flushblankhandling
+ \settrue\c_space_vspacing_done
+ \attribute\skipcategoryattribute \plusthree
+ \attribute\skippenaltyattribute #1\relax
+ \flushblankhandling}
+
+\unexpanded\def\startblankhandling % move this to \vspacing
+ {\par
+ \ifvmode
+ \expandafter\dostartblankhandling
+ \else
+ \expandafter\nostartblankhandling
+ \fi}
+
+\unexpanded\def\nostartblankhandling#1\stopblankhandling
+ {}
+
+\def\dostartblankhandling
+ {\begingroup
+ \setfalse\c_space_vspacing_done
+ \setfalse\c_space_ignore_parskip
+ \the\everybeforeblankhandling}
+
+\unexpanded\def\stopblankhandling
+ {\the\everyafterblankhandling
+ \ifconditional\c_space_vspacing_done
+ \vskip\s_spac_vspacing_temp
+ \fi
+ \ifconditional\c_space_ignore_parskip
+ \endgroup\ignoreparskip
+ \else
+ \endgroup
+ \fi}
+
+\unexpanded\def\flushblankhandling
+ {\the\everyafterblankhandling
+ \ifconditional\c_space_vspacing_done
+ \vskip\s_spac_vspacing_temp
+ \fi
+ \setfalse\c_space_vspacing_done
+ \the\everybeforeblankhandling}
+
+\unexpanded\def\addpredefinedblankskip#1#2%
+ {\settrue\c_space_vspacing_done
+ \advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax}
+
+% \unexpanded\def\addpredefinedblankskip#1#2%
+% {\settrue\c_space_vspacing_done
+% \advance\s_spac_vspacing_temp#1\dimexpr\the\csname\ifgridsnapping g\else n\fi>#2\endcsname\relax}
+
+\unexpanded\def\addaskedblankskip#1#2%
+ {\settrue\c_space_vspacing_done
+ \advance\s_spac_vspacing_temp#1\dimexpr#2\relax}
+
+% The main spacer:
+
+\unexpanded\def\vspacing
+ {\doifelsenextoptionalcs\spac_vspacing_yes\spac_vspacing_nop}
+
+\def\spac_vspacing_yes
+ {\ifinpagebody % somewhat weird
+ \expandafter\spac_vspacing_yes_indeed
+ \orelse\ifconditional\c_spac_packed_blank
+ \expandafter\spac_vspacing_yes_indeed
+ \else
+ \expandafter\spac_vspacing_yes_ignore
+ \fi}
+
+\def\spac_vspacing_nop
+ {\ifinpagebody % somewhat weird
+ \expandafter\spac_vspacing_nop_indeed
+ \orelse\ifconditional\c_spac_packed_blank
+ \expandafter\spac_vspacing_nop_indeed
+ \else
+ \expandafter\spac_vspacing_nop_ignore
+ \fi}
+
+\def\spac_vspacing_yes_indeed[#1]%
+ {\ifmmode\else\par\clf_vspacing{#1}\fi}
+
+\def\spac_vspacing_yes_ignore[#1]%
+ {\ifmmode\else\par\fi}
+
+\def\spac_vspacing_nop_indeed
+ {\ifmmode\else\par\clf_vspacing{\currentvspacing}\fi}
+
+\def\spac_vspacing_nop_ignore
+ {\ifmmode\else\par\fi}
+
+\installcorenamespace{vspacing}
+
+\unexpanded\def\directvspacing#1%
+ {\par
+ \ifchkdim#1\or
+ \spac_vspacing_dim_preset{\the\dimexpr#1}%
+ \orelse\ifcsname\??vspacing#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspacing_yes_preset{#1}%
+ \fi}
+
+\def\spac_vspacing_dim_preset#1%
+ {\ifcsname\??vspacing#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspacing_yes_preset{#1}%
+ \fi}
+
+\def\spac_vspacing_yes_preset#1%
+ {\setxvalue{\??vspacing#1}{\clf_vspacing{#1}}%
+ %\writestatus{}{}%
+ %\writestatus{#1}{\expandafter\meaning\csname\??vspacing#1\endcsname}%
+ %\writestatus{}{}%
+ \csname\??vspacing#1\endcsname}
+
+\def\spac_vspacing_yes_indeed[#1]%
+ {\ifmmode\else
+ \directvspacing{#1}%
+ \fi}
+
+\def\spac_vspacing_nop_indeed
+ {\ifmmode\else
+ \directvspacing\currentvspacing
+ \fi}
+
+\def\directdefaultvspacing
+ {\ifinpagebody % somewhat weird
+ \directvspacing\currentvspacing
+ \orelse\ifconditional\c_spac_packed_blank
+ \directvspacing\currentvspacing
+ \fi}
+
+\def\directcheckedvspacing
+ {\ifinpagebody % somewhat weird
+ \expandafter\directvspacing
+ \orelse\ifconditional\c_spac_packed_blank
+ \expandafter\directvspacing
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\useblankparameter#1% faster local variant
+ {\edef\m_spac_blank_asked{#1\c!blank}%
+ \ifx\m_spac_blank_asked\empty\else
+ \directvspacing\m_spac_blank_asked
+ \fi}
+
+%D Handy (and faster):
+
+\unexpanded\def\directvpenalty#1%
+ {\begingroup
+ \attribute\skipcategoryattribute \plusthree
+ \attribute\skippenaltyattribute #1\relax
+ \attribute\skiporderattribute \attributeunsetvalue
+ \vskip\zeropoint
+ \endgroup}
+
+\unexpanded\def\directvskip#1%
+ {\begingroup
+ \attribute\skipcategoryattribute \plusone
+ \attribute\skippenaltyattribute \attributeunsetvalue
+ \attribute\skiporderattribute \attributeunsetvalue
+ \vskip#1\relax
+ \endgroup}
+
+%D These depend on bigskipamount cum suis so we'd better sync them:
+
+\unexpanded\def\setupvspacing
+ {\doifelsenextoptionalcs\setupvspacing_yes\setupvspacing_nop}
+
+\let\currentvspacing\s!default % hm, default, standard ...
+
+\def\setupvspacing_yes[#1]%
+ {\edef\currentvspacing{#1}%
+ \spac_whitespace_setup_nop % yes or no, was forgotten
+ }
+
+\def\setupvspacing_nop
+ {\ifx\empty\currentvspacing % mistakenly had an \else
+ \let\currentvspacing\s!default
+ \fi
+ \spac_whitespace_setup_nop}
+
+\unexpanded\def\restorestandardblank % or default ?
+ {\let\currentvspacing\v!standard}
+
+\let\synchronizevspacing\setupvspacing_nop
+
+%D The \type {category:4} is default.
+
+\definevspacingamount[\v!none] [\zeropoint] [\zeropoint]
+\definevspacingamount[\v!big] [\bigskipamount] [\bodyfontlineheight]
+\definevspacingamount[\v!medium] [\medskipamount] [.5\bodyfontlineheight]
+\definevspacingamount[\v!small] [\smallskipamount] [.25\bodyfontlineheight]
+\definevspacingamount[\v!line] [\openlineheight] [\bodyfontlineheight]
+\definevspacingamount[\v!halfline] [.5\openlineheight] [.5\bodyfontlineheight]
+\definevspacingamount[\v!quarterline] [.25\openlineheight] [.25\bodyfontlineheight]
+\definevspacingamount[\v!formula] [\medskipamount] [.5\bodyfontlineheight]
+\definevspacingamount[\v!white] [\parskip] [\bodyfontwhitespace]
+\definevspacingamount[\v!height] [\strutht] [\bodyfontstrutheight]
+\definevspacingamount[\v!depth] [\strutdp] [\bodyfontstrutdepth]
+
+\definevspacingamount[\v!standard] [.75\openlineheight] [.75\openlineheight] % mkii compatible
+
+\def\bodyfontwhitespace
+ {\dimexpr
+ \ifdim\parskip=\zeropoint
+ \zeropoint
+ \orelse\ifgridsnapping
+ \bodyfontlineheight
+ \else
+ \parskip
+ \fi
+ \relax}
+
+%D used in itemize \unknown\ always test this:
+
+\newdimen\d_spac_overlay
+
+\def\spac_overlay_lines
+ {\directcheckedvspacing{\v!back,\v!overlay}% \blank[\v!back,\v!overlay]%
+ \nointerlineskip}
+
+% \startitemize[n]
+% \item \input zapf
+% \item \startitemize[a]
+% \item \input knuth
+% \stopitemize
+% \stopitemize
+%
+% \strut \hfill first line \blank[overlay] second line \hfill \strut
+%
+% \ruledvbox {
+% \strut \hfill line 1 \blank[overlay]
+% line 2 \hfill \strut \blank[overlay]
+% \strut \hfill line 3 \hfill \strut
+% }
+%
+% \dorecurse{50}
+% {\startitemize[n] \startitem \startitemize[a] \item #1 \stopitemize \stopitem \stopitemize}
+
+\definevspacing[\v!preference][penalty:-500] % goodbreak
+\definevspacing[\v!samepage] [penalty:10000] % nobreak
+
+\definevspacing[\v!always] [category:0] % hm, internally it's discard
+\definevspacing[\v!max] [category:1]
+\definevspacing[\v!force] [category:2]
+\definevspacing[\v!disable] [category:5]
+\definevspacing[\v!nowhite] [category:6]
+\definevspacing[\v!back] [category:7]
+\definevspacing[\v!packed] [category:8] % noparskip (kind of special)
+\definevspacing[\v!overlay] [category:9]
+\definevspacing[\v!enable] [category:10]
+
+%definevspacing[\v!noparskip] [category:8]
+%definevspacing[\v!notopskip] [category:11]
+
+\definevspacing[\v!weak] [order:0]
+\definevspacing[\v!strong] [order:100]
+
+\definevspacing[\s!default] [\v!white] % was big for a while
+
+\newcount\c_spac_vspacing_special_base \c_spac_vspacing_special_base = 32250 % 4000
+\newcount\c_spac_vspacing_special_step \c_spac_vspacing_special_step = 10 % 250
+\newcount\c_spac_vspacing_special_done
+
+% 2019-05-31 : upgraded a bit to more distinctive samepage-[level]-[0|1|2] names
+
+\unexpanded\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m
+ {\begingroup
+ \scratchcounterone\numexpr\plusthree*#1+#2\relax
+ \scratchcountertwo\numexpr\c_spac_vspacing_special_base+\c_spac_vspacing_special_step*\scratchcounterone\relax
+ %\writestatus{defined}{\v!samepage-\number#1-\number#2\space=>\space penalty:\the\scratchcountertwo}%
+ \normalexpanded{\definevspacing[\v!samepage-\number#1-\number#2][penalty:\the\scratchcountertwo]}%
+ \endgroup}
+
+\unexpanded\def\spac_vspacing_define_same_page#1%
+ {\dostepwiserecurse\c_spac_vspacing_special_done{#1}\plusone
+ {\spac_vspacing_define_same_step\recurselevel\zerocount % before
+ \spac_vspacing_define_same_step\recurselevel\plusone % after
+ \spac_vspacing_define_same_step\recurselevel\plustwo}% % whatever
+ \global\c_spac_vspacing_special_done#1\relax}
+
+\spac_vspacing_define_same_page{12} % 12 levels should be more than enough as a start
+
+\def\spac_vspacing_same_page#1#2% level offset (starts at 0)
+ {\ifnum#1>\c_spac_vspacing_special_done
+ \spac_vspacing_define_same_page{#1}%
+ \fi
+ %\writestatus{used}{\v!samepage-\number#1-\number#2}%
+ \vspacing[\v!samepage-\number#1-\number#2]}
+
+\definevspacing[\v!default] [\v!big] % todo: needs to adapt to \setupblank
+\definevspacing[\v!before] [\v!default] % but we need to avoid circular references
+\definevspacing[\v!inbetween][\v!default] % then
+\definevspacing[\v!after] [\v!before]
+
+\setupvspacing
+ [\v!big] % alternatively [\v!standard]
+
+%D Maybe at some point we will differ between \type {\vspacing} and \type {\blank}
+%D (we needed the first one while playing with the new code).
+
+% We keep this one as reference
+%
+% \unexpanded\def\inhibitblank
+% {\vspacing[\v!disable]}
+%
+% but use the following more efficient variant instead:
+
+\unexpanded\def\inhibitblank
+ {\ifvmode
+ \begingroup
+ \attribute\skipcategoryattribute\plusfive
+ \vskip\zeropoint
+ \endgroup
+ \fi}
+
+\let\doinhibitblank\inhibitblank % keep this command, used in styles
+
+\let\defineblank \definevspacing
+\let\setupblank \setupvspacing
+\let\blank \vspacing
+\let\synchronizeblank \synchronizevspacing
+\let\defineblankmethod\definevspacingamount
+
+%D The following command is for Wolfgang. It has to be used with care as it does
+%D {\em not} work in tandem with the other spacing commands.
+
+\installcorenamespace{vspace}
+
+\unexpanded\def\definevspace
+ {\dotripleempty\spac_vspace_define}
+
+\def\spac_vspace_define[#1][#2][#3]%
+ {\ifthirdargument
+ \setvalue{\??vspace#1:#2}{#3}%
+ \else
+ \setvalue{\??vspace:#1}{#2}%
+ \fi}
+
+\letvalue{\??vspace:\s!unknown}\zeropoint
+
+\unexpanded\def\vspace
+ {\dodoubleempty\spac_vspace_inject}
+
+\def\spac_vspace_unknown
+ {\csname\??vspace:\s!unknown\endcsname}
+
+\def\spac_vspace_inject[#1][#2]% use \lastnamedcs
+ {\par
+ \ifvmode
+ \removelastskip
+ \vskip
+ \ifsecondargument
+ \ifcsname\??vspace#1:#2\endcsname
+ \lastnamedcs
+ \orelse\ifcsname\??vspace:#2\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspace_unknown
+ \fi
+ \orelse\iffirstargument
+ \ifcsname\??vspace:#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspace_unknown
+ \fi
+ \else
+ \ifcsname\??vspace:\s!default\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspace_unknown
+ \fi
+ \fi
+ \relax
+ \fi}
+
+%D Some preliminary code: a simple and fast hanger, for usage in macros.
+
+\installcorenamespace {hanging}
+
+\installdirectcommandhandler \??hanging {hanging}
+
+\setuphanging
+ [\c!distance=.5\emwidth,
+ \c!location=\v!left,
+ \c!n=\zerocount]
+
+\unexpanded\def\starthanging
+ {\dontleavehmode\bgroup
+ \dosingleempty\spac_hanging_start}
+
+\unexpanded\def\stophanging
+ {\endgraf
+ \egroup}
+
+\let\m_spac_hanging_location\empty
+
+\def\spac_hanging_start[#1]%
+ {\doifelseassignment{#1}
+ {\let\m_spac_hanging_location\empty
+ \setupcurrenthanging[#1]}%
+ {\edef\m_spac_hanging_location{#1}}%
+ \ifx\m_spac_hanging_location\empty
+ \edef\m_spac_hanging_location{\directhangingparameter\c!location}%
+ \fi
+ \dowithnextboxcs\spac_hanging_finish\hbox}
+
+\def\spac_hanging_finish
+ {\scratchdistance\directhangingparameter\c!distance\relax
+ \ifdim\ht\nextbox>\strutht
+ \setbox\nextbox\tbox{\box\nextbox}%
+ \fi
+ \scratchcounter\directhangingparameter\c!n\relax
+ \ifnum\scratchcounter>\zerocount
+ \hangafter-\scratchcounter
+ \else
+ \getboxheight\scratchdimen\of\box\nextbox
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \fi
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \scratchwidth\dimexpr\wd\nextbox+\scratchdistance\relax
+ \ifx\m_spac_hanging_location\v!right
+ \hangindent\ifconditional\displaylefttoright-\fi\scratchwidth
+ \rlap{\hskip\dimexpr\hsize-\leftskip-\wd\nextbox\relax\box\nextbox}% \leftskip is new
+ \else
+ \hangindent\ifconditional\displaylefttoright\else-\fi\scratchwidth
+ \llap{\box\nextbox\hskip\scratchdistance}%
+ \fi
+ \ignorespaces}
+
+
+%D \macros
+%D {startfixed}
+%D
+%D \starttyping
+%D \startitemize
+%D \startitem \externalfigure[cow][height=1cm] \stopitem
+%D \startitem \externalfigure[cow][height=1cm] \stopitem
+%D
+%D \startitem \startfixed \externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[high]\externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[low] \externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[lohi]\externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D
+%D \startitem test \par \startfixed \externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[high]\externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[low] \externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[lohi]\externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \stopitemize
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace{fixedalternatives}
+
+\unexpanded\def\startfixed
+ {\bgroup
+ \dosingleempty\typo_fixed_start}
+
+\def\typo_fixed_start
+ {\ifhmode
+ \expandafter\typo_fixed_start_h
+ \else
+ \expandafter\typo_fixed_start_v
+ \fi}
+
+\def\typo_fixed_start_h[#1]%
+ {\let\stopfixed\typo_fixed_stop_h
+ \dowithnextbox{\typo_fixed_finish{#1}}%
+ \vbox\bgroup
+ %ignorespaces
+ \setlocalhsize}
+
+\unexpanded\def\typo_fixed_stop_h
+ {%removeunwantedspaces
+ \egroup
+ \egroup}
+
+\def\typo_fixed_start_v[#1]%
+ {\let\stopfixed\typo_fixed_stop_v
+ \startbaselinecorrection}
+
+\unexpanded\def\typo_fixed_stop_v
+ {\stopbaselinecorrection
+ \egroup}
+
+\letvalue{\??fixedalternatives \v!high}\bbox
+\letvalue{\??fixedalternatives \v!low}\tbox
+\letvalue{\??fixedalternatives \v!middle}\vcenter
+\letvalue{\??fixedalternatives \v!lohi}\vcenter
+\letvalue{\??fixedalternatives\s!unknown}\tbox
+\letvalue{\??fixedalternatives\s!default}\tbox
+
+\unexpanded\def\typo_fixed_finish#1%
+ {\expandnamespacevalue\??fixedalternatives{#1}\s!default{\box\nextbox}}
+
+% %D Forgotten already:
+%
+% \def\shapefill{\vskip\zeropoint\s!plus\lineheight\s!minus\lineheight\relax}
+
+%D Nasty:
+
+% \writestatus{1}{\the\prevdepth} \blank[force,5*big] { \writestatus{1}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{2}{\the\prevdepth} \blank[force,5*big] { \writestatus{2}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{3}{\the\prevdepth} \blank[force,5*big] { \writestatus{3}{\the\prevdepth} \baselineskip5cm xxxxxxxxx \par } \page
+% \writestatus{4}{\the\prevdepth} \input tufte \page
+% \writestatus{5}{\the\prevdepth} \input tufte \page
+% \writestatus{6}{\the\prevdepth} \blank[force,5*big] { \writestatus{6}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+
+% \writestatus{1}{\the\prevdepth} \null\vskip4cm { \writestatus{1}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{2}{\the\prevdepth} \null\vskip4cm { \writestatus{2}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{3}{\the\prevdepth} \null\vskip4cm { \writestatus{3}{\the\prevdepth} \baselineskip5cm xxxxxxxxx \par } \page
+% \writestatus{4}{\the\prevdepth} \input tufte \page
+% \writestatus{5}{\the\prevdepth} \input tufte \page
+% \writestatus{6}{\the\prevdepth} \null\vskip4cm { \writestatus{6}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+
+\appendtoks
+ \ifvmode\prevdepth\zeropoint\fi % consistent, else first page -1000pt .. needed for fixed,3*big first/successive pages consistency
+\to \everystarttext
+
+\prevdepth\zeropoint
+
+%D Helper:
+
+\unexpanded\def\checkedblank[#1]%
+ {\edef\p_blank{#1}%
+ \ifx\p_blank\empty
+ % ignore
+ \orelse\ifx\p_blank\v!none
+ % ignore
+ \else
+ \blank[\p_blank]%
+ \fi}
+
+% \setupwhitespace[line]
+% \prerollblank[2*line] \the\prerolledblank
+% \prerollblank[-2*line] \the\prerolledblank
+
+\newskip\prerolledblank
+
+\unexpanded\def\prerollblank[#1]%
+ {\begingroup
+ \edef\p_blank{#1}%
+ \ifx\p_blank\empty
+ \global\prerolledblank\zeropoint
+ \orelse\ifx\p_blank\v!none
+ \global\prerolledblank\zeropoint
+ \else
+ % don't mess with \arskip here!
+ \scratchskip\plusten\lineheight
+ \setbox\scratchbox\vbox
+ {\vskip\scratchskip
+ \kern\zeropoint
+ \blank[\p_blank]}%
+ % \dimexpr doesn't work well with skips
+ \advance\scratchskip-\ht\scratchbox
+ \global\prerolledblank-\scratchskip
+ \fi
+ \endgroup}
+
+\newcount\c_spac_vspacing_ignore_parskip
+
+% \setupwhitespace[line]
+% \setuphead[subject][after={\blank[packed]},style=\bfb]
+% \subject{foo}
+% test \par
+% test \par
+% \blank[packed] % \ignoreparskip
+% test \par
+% test \par
+% \ignoreparskip
+% test \par
+% test \par
+% \setuphead[subject][after={\blank[nowhite]},style=\bfb]
+% \subject{foo}
+% test \par
+% test \par
+
+\unexpanded\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index d65f4089b..c0b856eb0 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 2db709d41..5d07a4305 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-itm.mklx b/tex/context/base/mkiv/strc-itm.mklx
new file mode 100644
index 000000000..959801c8b
--- /dev/null
+++ b/tex/context/base/mkiv/strc-itm.mklx
@@ -0,0 +1,1854 @@
+%D \module
+%D [ file=strc-itm,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Itemgroups,
+%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.
+
+\writestatus{loading}{ConTeXt Structure Macros / Itemgroups}
+
+\registerctxluafile{strc-itm}{}
+
+%D As we analyze/register widths and such we could as well push and pop the numbers
+%D at the \LUA\ end (which saves a few calls).
+%D
+%D Cleaning up this module happened around the time when Kate Bush came up with the
+%D nicest numbered list of words: 50 Words For Snow. It's therefore no surprise that
+%D I had that cd running several times when updating this code. One of the
+%D highlights of 2011.
+%D
+%D This module needs to be rewritten but that is tricky with respect to
+%D compatibilitity. Basically each major variant (regular, text, columns,
+%D horizontal, etc) needs to be on its own.
+
+% todo: check breaks
+% todo: check grouping
+% todo: fixedconversion
+
+% \startitemize[n,packed]
+% \item test \item test \item test
+% \stopitemize
+%
+% \startitemize[n,packed,reverse]
+% \item test \item test \item test
+% \stopitemize
+%
+% \startitemize[n,packed,reverse] \item test \item test \stopitemize
+% \startitemize[continue]
+% \item test \startitemize[n,packed] \item test \item test \stopitemize
+% \item test
+% \item test
+% \stopitemize
+% \startitemize[continue] \item test \stopitemize
+%
+% \startitemize[n,packed] \item test \item test \stopitemize
+% \startitemize[continue] \item test \stopitemize
+% \startitemize[continue] \item test \stopitemize
+%
+% \setupwhitespace[big]
+% \starttext
+% test \startitemize[joinedup] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite,before] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite,after] \item test \item test \stopitemize test \par
+% \stoptext
+%
+% test / example
+%
+% \startnarrower[left] \startcolumns[n=3] \startitemize
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \stopcolumns\stopnarrower \blank
+%
+% \startnarrower[left] \startitemize[columns,three]
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \stopnarrower \blank
+%
+% \setupitemize[leftmargin=1.5em] \startitemize[columns,three]
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \blank
+%
+% beware, we don't group (yet) as we want to keep the left/right skip
+%
+% \startitemize
+% \startitem \stopitem
+% some intermediate text that will properly indent
+% \startitem \stopitem
+% \stopitem
+%
+% so we need to keep that property
+%
+% \startitemize
+% \starthead {xx} test \stophead
+% \startitem test \stopitem
+% \startitem test \stopitem
+% \stopitemize
+%
+% Sometimes the user demands get pretty weird:
+%
+% \startitemize
+% \item test
+% \item test
+% \headsym{xx} test \par test
+% \stopitemize
+%
+% aligned items
+%
+% \startitemize[n,fit,broad][itemalign=flushright]
+% \dorecurse{100}{\item The first item.}
+% \stopitemize
+%
+% \setupitemgroup[itemize][each][fit]
+% \setupitemgroup[itemize][each][distance=.5em,factor=1,itemalign=flushright]
+%
+% \startitemize[n]
+% \dorecurse{100}{\item The first item.}
+% \stopitemize
+%
+% \defineitemgroup[gbitemize]
+% \setupitemgroup[gbitemize][each][headstyle=bold]
+%
+% \startgbitemize
+% \txt{italian} some italians like this kind of cross||breed between
+% an itemize and a description
+% \txt{sicilians} i wonder how many sicilian mathematicians do a thesis
+% on the math involved in predicting the next big bang of the vulcano
+% \stopgbitemize
+%
+% \startitemize[n,repeat]
+% \noitem \startitemize[a] \item Item 1.a. \item Item 1.b. \stopitemize
+% \noitem \startitemize[a] \item Item 2.a. \item Item 2.b. \stopitemize
+% \stopitemize
+%
+% \startitemize[n,repeat][width=0pt]
+% \noitem \startitemize[a][width=2em] \item Item 1.a. \item Item 1.b. \stopitemize
+% \noitem \startitemize[a][width=2em] \item Item 2.a. \item Item 2.b. \stopitemize
+% \stopitemize
+%
+% \startbuffer
+% \item
+% \startitemize[n]
+% \item item 1.1
+% \item item 1.2
+% \startitemize[n] \item item 1.2.1 \item item 1.2.2 \stopitemize
+% \item item 1.3
+% \stopitemize
+% \item
+% \startitemize[n] \item item 2.1 \item item 2.2 \stopitemize
+% \item item 3
+% \startitemize[n] \item item 3.1 \item item 3.2 \stopitemize
+% \item
+% \startitemize[n] \item item 4.1 \item item 4.2 \stopitemize
+% \stopbuffer
+%
+% \startitemize[n,repeat,6*broad,packed] \getbuffer \stopitemize \blank[3*big]
+% \startitemize[n,repeat,packed] \getbuffer \stopitemize \blank[3*big]
+% \setupitemize[each][atmargin][width=3em]
+% \startitemize[n,repeat,packed] \getbuffer \stopitemize
+%
+% todo: assume startitem ... stopitem and do an autostopitem .. cleaner for
+% elements
+%
+% \startitemize[text][space=medium]
+% \item one \item two \item three
+% \stopitemize
+%
+% For Giuseppe "Oblomov" Bilotta, inspired on a suggestion by Taco
+% Hoekwater.
+%
+% \def\MyItemCommand#1{{\bf#1}\quad}
+% \setupitemgroup[itemize][command=\MyItemCommand]
+%
+% \startitemize
+% \item {test} is this okay?
+% \item {test} is this okay?
+% \item {test} is this okay?
+% \stopitemize
+
+\unprotect
+
+\newconditional\c_strc_itemgroups_sub
+\newconditional\c_strc_itemgroups_head
+\newconditional\c_strc_itemgroups_intro
+\newconditional\c_strc_itemgroups_randomize
+\newconditional\c_strc_itemgroups_horizontal
+\newconditional\c_strc_itemgroups_collecting
+\newconditional\c_strc_itemgroups_auto_intro
+\newconditional\c_strc_itemgroups_pack
+\newconditional\c_strc_itemgroups_paragraph
+\newconditional\c_strc_itemgroups_text
+\newconditional\c_strc_itemgroups_text_saved
+\newconditional\c_strc_itemgroups_first
+\newconditional\c_strc_itemgroups_before
+\newconditional\c_strc_itemgroups_after
+\newconditional\c_strc_itemgroups_nowhite
+\newconditional\c_strc_itemgroups_joined
+\newconditional\c_strc_itemgroups_reverse
+\newconditional\c_strc_itemgroups_continue
+\newconditional\c_strc_itemgroups_fitting
+\newconditional\c_strc_itemgroups_indented_first
+\newconditional\c_strc_itemgroups_inline
+\newconditional\c_strc_itemgroups_columns
+\newconditional\c_strc_itemgroups_concat
+\newconditional\c_strc_itemgroups_txt
+\newconditional\c_strc_itemgroups_extra
+\newconditional\c_strc_itemgroups_repeat
+
+% 0 = before/after
+% 1 = between unless before
+% 2 = between
+
+\newconstant \c_strc_itemgroups_spacing_mode \c_strc_itemgroups_spacing_mode\plustwo
+\newconditional\c_strc_itemgroups_optimize \settrue\c_strc_itemgroups_optimize
+\newconditional\c_strc_itemgroups_auto_concat \settrue\c_strc_itemgroups_auto_concat
+
+\newsignal \d_strc_itemgroups_signal
+
+\newbox \b_strc_itemgroups
+
+\newdimen \d_strc_itemgroups_list_width
+\newdimen \d_strc_itemgroups_asked_width
+
+\newdimen \d_strc_itemgroups_max_width % multipass
+\newcount \c_strc_itemgroups_max_items % multipass
+
+\newcount \c_strc_itemgroups_n_of_items
+\newcount \c_strc_itemgroups_nesting
+\newcount \c_strc_itemgroups_column_depth
+
+\def \v_strc_itemgroups_counter {itemgroup:\currentparentitemgroup}
+\let \m_strc_itemgroups_repeat_start \empty
+\def \v_strc_itemgroups_unknown_symbol {?}
+\let \m_strc_itemgroups_indenting \empty
+\let \m_strc_itemgroups_destination \empty
+
+\let \currentitemlevel \!!zerocount % public
+\def \currentnofitems {\the\c_strc_itemgroups_max_items}
+\def \currentitemnumber {\strc_counters_raw_sub\v_strc_itemgroups_counter\currentitemlevel} % public
+
+\newtoks \itemgroupcommands % maybe public
+
+\def \currentitemgroupsymbol {n} % here we cannot use a _ in the name
+\let \currentitemgroupconversionset \empty % here we cannot use a _ in the name
+\let \currentitemgroupsegments \empty
+
+\def\strc_itemgroups_register_status
+ {\clf_registeritemgroup{\currentparentitemgroup}\c_strc_itemgroups_nesting\c_strc_itemgroups_n_of_items\dimexpr\itemgroupparameter\c!maxwidth\relax}
+
+\def\strc_itemgroups_check_n_of_items % we could do this at the lua end and save a call (i.e. will be dimen and counter)
+ {\clf_analyzeitemgroup{\currentparentitemgroup}\c_strc_itemgroups_nesting\relax
+ \edef\currentnofitems{\the\c_strc_itemgroups_max_items}}
+
+% todo: \dodosetreference -> \strc_counters_register_component (to be checked)
+
+\def\strc_itemgroups_insert_reference % we will make a decent number helper
+ {\iftrialtypesetting \orelse \ifx\currentitemreference \empty \else
+ \strc_itemgroups_insert_reference_indeed
+ \fi}
+
+\def\strc_itemgroups_insert_extra_reference
+ {\iftrialtypesetting \orelse \ifx\currentitemreference \empty \else
+ \normalexpanded{\textreference[\currentitemreference]{\strc_itemgroups_extra_symbol}}%
+ \fi}
+
+\def\strc_itemgroups_insert_reference_indeed % maybe we need a 'frozen counter' numberdata blob / quick hack .. .mive this to strc-ref
+ {% needs testing, gave problems:
+ \setnextinternalreference
+ % no need to collect nodes in \b_strc_destination_nodes here ... maybe at some point
+ \strc_references_start_destination_nodes
+ % this is somewhat over the top ... we should use the counter's reference
+ \clf_setdestinationattribute
+ {%
+ metadata {%
+ kind {item}% was item, why?
+ \ifx\currentreferencecoding\s!xml
+ xmlroot {\xmldocument}% only useful when text
+ \fi
+ catcodes \catcodetable
+ }%
+ references {%
+ internal \locationcount % no: this spoils references
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ prefix {\referenceprefix}%
+ reference {\currentitemreference}%
+ }%
+ prefixdata {%
+ prefix {\namedcounterparameter\v_strc_itemgroups_counter\c!prefix}%
+ separatorset {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixseparatorset}%
+ conversion {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixconversion}%
+ conversionset {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixconversionset}%
+ set {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixset}%
+ segments {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixsegments}%
+ % segments {\askedprefixsegments}%
+ connector {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixconnector}%
+ }%
+ numberdata {%
+ numbers {\v_strc_itemgroups_counter}%
+ separatorset {\namedcounterparameter\v_strc_itemgroups_counter\c!numberseparatorset}%
+ % conversion {\namedcounterparameter\v_strc_itemgroups_counter\c!numberconversion}%
+ % conversionset {\namedcounterparameter\v_strc_itemgroups_counter\c!numberconversionset}%
+ % fixedconversion {\currentitemgroupconversionset}%
+ conversionset {fixed::\currentitemgroupconversionset}% temp hack
+ %
+ % for the moment no stopper, we need to make references configurable first
+ % stopper {\namedcounterparameter\v_strc_itemgroups_counter\c!numberstopper}%
+ segments {\namedcounterparameter\v_strc_itemgroups_counter\c!numbersegments}%
+ }%
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ % will become an option:
+ \ifnum\lastdestinationattribute>\zerocount
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \egroup
+ \fi}
+
+%D Defining and setup:
+
+\installcorenamespace{itemgroup}
+\installcorenamespace{itemgroupoption}
+\installcorenamespace{itemgroupsetting}
+\installcorenamespace{itemgroupkeyword}
+\installcorenamespace{itemgroupalign}
+\installcorenamespace{itemgrouplocal}
+\installcorenamespace{itemgroupglobal}
+\installcorenamespace{itemgroupdistance}
+\installcorenamespace{itemgroupstack}
+\installcorenamespace{itemgroupfirst}
+\installcorenamespace{itemgroupstart}
+
+\installcommandhandler \??itemgroup {itemgroup} \??itemgroup
+
+\let\setupitemgroups\setupitemgroup
+
+\appendtoks
+ \setuevalue{\e!start\currentitemgroup}{\startitemgroup[\currentitemgroup]}%
+ \setuevalue{\e!stop \currentitemgroup}{\stopitemgroup}%
+ \setuevalue{\e!setup\currentitemgroup\e!endsetup}{\setupitemgroup[\currentitemgroup]}% obsolete
+ \let\currentparentitemgroup\currentitemgroup
+ \definecounter[\v_strc_itemgroups_counter]%
+ % beware ... we cannot use _ as the conversion set is not expanded
+ % \defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]%
+\to \everydefineitemgroup
+
+%D Global states
+
+\def\strc_itemgroups_store_continue_state#options#settings%
+ {\setxvalue{\??itemgroupoption \currentitemgroup}{\strc_itemgroups_process_options{#options}}%
+ \setgvalue{\??itemgroupsetting\currentitemgroup}{\setupcurrentitemgroup[#settings]}}
+
+\def\strc_itemgroups_fetch_continue_state
+ {\csname\??itemgroupoption \currentitemgroup\endcsname
+ \csname\??itemgroupsetting\currentitemgroup\endcsname}
+
+\def\strc_itemgroups_reset_continue_state
+ {\expandafter\glet\csname\??itemgroupoption \currentitemgroup\endcsname\relax
+ \expandafter\glet\csname\??itemgroupsetting\currentitemgroup\endcsname\relax}
+
+% These will become keywords. We will also add a feature to keep the while set
+% together.
+
+\definevspacing[\v!item @0] [penalty:0] % allow
+\definevspacing[\v!item @10000] [penalty:10000] % no
+\definevspacing[\v!item @-5] [penalty:-5]
+\definevspacing[\v!item @5] [penalty:5]
+\definevspacing[\v!item @500] [penalty:500] % discourage .. too low, 5000 is better
+
+\def\strc_itemgroups_insert_break_when_needed#break%
+ {\ifconditional\c_strc_itemgroups_optimize
+ \ifconditional\c_strc_itemgroups_text \else
+ #break\relax
+ \fi
+ \fi}
+
+\def\strc_itemgroups_insert_breakallow {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_breakallow_indeed}
+\def\strc_itemgroups_insert_breakno {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_breakno_indeed }
+\def\strc_itemgroups_insert_break {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_break_indeed }
+\def\strc_itemgroups_insert_nobreak {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_nobreak_indeed }
+
+\def\strc_itemgroups_insert_breakallow_indeed{\vspacing[\v!item @0]}
+\def\strc_itemgroups_insert_breakno_indeed {\vspacing[\v!item @10000]}
+\def\strc_itemgroups_insert_break_indeed {\flushnotes
+ \vspacing[\v!item @-5]}
+\def\strc_itemgroups_insert_nobreak_indeed {\flushnotes
+ \ifinsidecolumns % todo
+ \vspacing[\v!item @5]%
+ \else
+ \vspacing[\v!item @500]%
+ \fi}
+
+\unexpanded\def\strc_itemgroups_process_options#options%
+ {\processcommacommand[#options]\strc_itemgroups_process_option} % expansion of options is handy for xml
+
+% \installcommalistprocessorcommand \strc_itemgroups_process_option_list \strc_itemgroups_process_option
+%
+% \unexpanded\def\strc_itemgroups_process_options#options%
+% {\normalexpanded{\strc_itemgroups_process_option_list[#options]}} % expansion of options is handy for xml
+
+\def\strc_itemgroups_process_option#option%
+ {\edef\itemgroupconstantvalue{#option}%
+ \ifx\itemgroupconstantvalue\empty\else
+ \splitatasterisk\itemgroupconstantvalue\itemgroupfirst\itemgroupsecond
+ \ifx\itemgroupsecond\empty
+ \let\itemgroupsecond\itemgroupfirst
+ \let\itemgroupfirst\!!plusone
+ \fi
+ \ifcsname\??itemgroupkeyword\itemgroupsecond\endcsname
+ \lastnamedcs
+ \else
+ \strc_itemgroups_set_symbol\itemgroupconstantvalue
+ \fi
+ \fi}
+
+\def\strc_itemgroups_process_set_option_pack
+ {\ifcase\c_strc_itemgroups_nesting \else
+ \settrue\c_strc_itemgroups_pack
+ \fi}
+
+\def\strc_itemgroups_process_set_option_unpack
+ {\ifcase\c_strc_itemgroups_nesting\else
+ \setfalse\c_strc_itemgroups_pack
+ \fi}
+
+\setvalue{\??itemgroupkeyword\!!zerocount }{} % ignore 0
+\setvalue{\??itemgroupkeyword\v!packed }{\strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!unpacked }{\strc_itemgroups_process_set_option_unpack}
+\setvalue{\??itemgroupkeyword\v!intro }{\settrue\c_strc_itemgroups_intro} % here? not set to false
+\setvalue{\??itemgroupkeyword\v!autointro }{\settrue\c_strc_itemgroups_auto_intro}
+\setvalue{\??itemgroupkeyword\v!broad }{\ifx\itemgroupfirst\empty
+ \let\itemgroupfirst\!!plusone
+ \fi
+ \letitemgroupparameter\c!factor\itemgroupfirst}
+\setvalue{\??itemgroupkeyword\v!text }{\settrue\c_strc_itemgroups_text
+ \settrue\c_strc_itemgroups_inline
+ \settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!before }{\settrue\c_strc_itemgroups_before}
+\setvalue{\??itemgroupkeyword\v!after }{\settrue\c_strc_itemgroups_after}
+\setvalue{\??itemgroupkeyword\v!nowhite }{\settrue\c_strc_itemgroups_nowhite}
+\setvalue{\??itemgroupkeyword\v!margin }{\setitemgroupparameter\c!width{-2em}} % signal
+\setvalue{\??itemgroupkeyword\v!inmargin }{\setitemgroupparameter\c!width{-2em}} % signal
+\setvalue{\??itemgroupkeyword\v!atmargin }{\ifnum\c_strc_itemgroups_nesting>\plusone
+ \setitemgroupparameter\c!width{0em}%
+ \fi} % signal
+\setvalue{\??itemgroupkeyword\v!intext }{\settrue\c_strc_itemgroups_inline}
+\setvalue{\??itemgroupkeyword\v!loose }{\setfalse\c_strc_itemgroups_optimize}
+\setvalue{\??itemgroupkeyword\v!fit }{\settrue\c_strc_itemgroups_fitting}
+\setvalue{\??itemgroupkeyword\v!nofit }{\setfalse\c_strc_itemgroups_fitting}
+\setvalue{\??itemgroupkeyword\v!paragraph }{\settrue\c_strc_itemgroups_paragraph
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!joinedup }{\settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!notjoinedup}{\setfalse\c_strc_itemgroups_joined}
+\setvalue{\??itemgroupkeyword\v!serried }{\edef\itemgroupfirst{-\ifx\itemgroupfirst\empty1\else\itemgroupfirst\fi}%
+ \letitemgroupparameter\c!factor\itemgroupfirst}
+\setvalue{\??itemgroupkeyword\v!stopper }{\letitemgroupparameter\c!placestopper\v!yes} % keep {}
+\setvalue{\??itemgroupkeyword\v!nostopper }{\letitemgroupparameter\c!placestopper\v!no} % keep {}
+\setvalue{\??itemgroupkeyword\v!repeat }{\settrue\c_strc_itemgroups_repeat}
+\setvalue{\??itemgroupkeyword\v!norepeat }{\setfalse\c_strc_itemgroups_repeat}
+\setvalue{\??itemgroupkeyword\v!reverse }{\settrue\c_strc_itemgroups_reverse}
+\setvalue{\??itemgroupkeyword\v!columns }{\settrue\c_strc_itemgroups_columns}
+\setvalue{\??itemgroupkeyword\v!one }{\letitemgroupparameter\c!n\plusone}
+\setvalue{\??itemgroupkeyword\v!two }{\letitemgroupparameter\c!n\plustwo}
+\setvalue{\??itemgroupkeyword\v!three }{\letitemgroupparameter\c!n\plusthree}
+\setvalue{\??itemgroupkeyword\v!four }{\letitemgroupparameter\c!n\plusfour}
+\setvalue{\??itemgroupkeyword\v!five }{\letitemgroupparameter\c!n\plusfive}
+\setvalue{\??itemgroupkeyword\v!six }{\letitemgroupparameter\c!n\plussix}
+\setvalue{\??itemgroupkeyword\v!seven }{\letitemgroupparameter\c!n\plusseven}
+\setvalue{\??itemgroupkeyword\v!eight }{\letitemgroupparameter\c!n\pluseight}
+\setvalue{\??itemgroupkeyword\v!nine }{\letitemgroupparameter\c!n\plusnine}
+%setvalue{\??itemgroupkeyword\v!standard }{\setupcurrentitemgroup
+% [\c!width =1.5\emwidth,%
+% \c!distance =.5\emwidth,%
+% \c!factor =0,%
+% \c!inner =,%
+% \c!beforehead=,%
+% \c!afterhead =\blank,%
+% \c!before =\blank,%
+% \c!inbetween =\blank,%
+% \c!after =\blank]}
+\setvalue{\??itemgroupkeyword\v!standard }{\setitemgroupparameter\c!width {1.5\emwidth}%
+ \setitemgroupparameter\c!distance {.5\emwidth}%
+ \letitemgroupparameter\c!factor \!!zerocount
+ \letitemgroupparameter\c!inner \empty
+ \letitemgroupparameter\c!beforehead\empty
+ \letitemgroupparameter\c!afterhead \blank
+ \letitemgroupparameter\c!before \blank
+ \letitemgroupparameter\c!inbetween \blank
+ \letitemgroupparameter\c!after \blank}
+
+
+\def\strc_itemgroups_initialize_local
+ {\setfalse\c_strc_itemgroups_inline
+ \setfalse\c_strc_itemgroups_concat
+ \setfalse\c_strc_itemgroups_txt
+ %
+ \setfalse\c_strc_itemgroups_reverse
+ \setfalse\c_strc_itemgroups_intro
+ \setfalse\c_strc_itemgroups_auto_intro
+ \setfalse\c_strc_itemgroups_before
+ \setfalse\c_strc_itemgroups_after
+ \setfalse\c_strc_itemgroups_nowhite
+ \setfalse\c_strc_itemgroups_randomize
+ \setfalse\c_strc_itemgroups_horizontal
+ \setfalse\c_strc_itemgroups_collecting
+ \setfalse\c_strc_itemgroups_intro
+ \setfalse\c_strc_itemgroups_continue
+ % this will be a constant
+ \setfalse\c_strc_itemgroups_head
+ \setfalse\c_strc_itemgroups_sub
+ \setfalse\c_strc_itemgroups_symbol
+ \setfalse\c_strc_itemgroups_columns
+ % to be checked
+ \let\m_strc_itemgroups_destination\empty
+ \let\strc_itemgroups_used_symbol \empty % ** start value
+ \let\strc_itemgroups_margin_symbol\empty
+ \let\strc_itemgroups_extra_symbol \empty
+ %
+ \global\letitemgroupparameter\c!maxwidth\!!zeropoint
+ }
+
+\setvalue{\??itemgroupfirst\v!intro }{\settrue\c_strc_itemgroups_intro}
+\setvalue{\??itemgroupfirst\v!continue }{\settrue\c_strc_itemgroups_continue}
+\setvalue{\??itemgroupfirst\v!random }{\settrue\c_strc_itemgroups_randomize
+ \settrue\c_strc_itemgroups_collecting}
+\setvalue{\??itemgroupkeyword\v!horizontal}{\settrue\c_strc_itemgroups_horizontal
+ \settrue\c_strc_itemgroups_collecting
+ \settrue\c_strc_itemgroups_inline
+ \settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+
+\def\strc_itemgroups_preset_stage_one#options%
+ {\processcommacommand[#options]\strc_itemgroups_preset_stage_one_indeed}
+
+% \installcommalistprocessorcommand \strc_itemgroups_preset_stage_one_list \strc_itemgroups_preset_stage_one_indeed
+%
+% \def\strc_itemgroups_preset_stage_one#options%
+% {\normalexpanded{\strc_itemgroups_preset_stage_one_list[#options]}}
+
+\def\strc_itemgroups_preset_stage_one_indeed#option%
+ {\ifcsname\??itemgroupfirst#option\endcsname
+ \lastnamedcs
+ \fi}
+
+\ifdefined\dotagsetitemgroup \else \let\dotagsetitemgroup\relax \fi
+\ifdefined\dotagsetitem \else \let\dotagsetitem \gobbleoneargument \fi
+
+\def\strc_itemgroups_tag_start_group
+ {\dostarttaggedchained\t!itemgroup\currentparentitemgroup\??itemgroup
+ \dotagsetitemgroup}
+
+\def\strc_itemgroups_tag_stop_group
+ {\dostoptagged}
+
+\def\strc_itemgroups_before_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \ifconditional\c_strc_itemgroups_before
+ \ifcase\c_strc_itemgroups_nesting\or\itemgroupparameter\c!before\fi
+ \else
+ \nowhitespace
+ \fi
+ \orelse\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!before
+ \fi}
+
+\def\strc_itemgroups_after_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \ifconditional\c_strc_itemgroups_after
+ \ifcase\c_strc_itemgroups_nesting\or\itemgroupparameter\c!after\fi
+ \else
+ \nowhitespace
+ \fi
+ \orelse\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!after
+ \fi}
+
+\def\strc_itemgroups_between_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \orelse\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!inbetween
+ \fi}
+
+\def\strc_itemgroups_before_head_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \orelse\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!beforehead
+ \fi}
+
+\def\strc_itemgroups_after_head_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \orelse\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!afterhead
+ \fi}
+
+% compatible setup command:
+
+\let\strc_itemgroups_normal_setup\setupitemgroup
+
+\unexpanded\def\setupitemgroup
+ {\doquadrupleempty\strc_itemgroups_setup}
+
+\def\strc_itemgroups_setup[#category][#levels][#options][#settings]% category level|each options|settings settings|options
+ {\edef\strc_itemgroups_setup_what{#levels}%
+ \iffourthargument
+ \ifx\strc_itemgroups_setup_what\v!each
+ \strc_itemgroups_setup_each{#category}{#options}%
+ \strc_itemgroups_setup_each{#category}{#settings}%
+ \else
+ \strc_itemgroups_setup_list{#levels}{#category}{#options}%
+ \strc_itemgroups_setup_list{#levels}{#category}{#settings}%
+ \fi
+ \orelse\ifthirdargument
+ \ifx\strc_itemgroups_setup_what\v!each
+ \strc_itemgroups_setup_each{#category}{#options}%
+ \else
+ \strc_itemgroups_setup_list{#levels}{#category}{#options}%
+ \fi
+ \orelse\ifsecondargument
+ \strc_itemgroups_setup_each{#category}{#levels}%
+ \else
+ \strc_itemgroups_normal_setup[#category]% == settings
+ \fi}
+
+% can be made a bit faster
+
+% \def\strc_itemgroups_setup_each#category#whatever%
+% {\doifelseassignment{#whatever}
+% {\strc_itemgroups_normal_setup[#category][#whatever]}
+% {\strc_itemgroups_normal_setup[#category][\c!option={#whatever}]}}
+
+\def\strc_itemgroups_setup_each#category#whatever%
+ {\ifcondition\validassignment{#whatever}%
+ \strc_itemgroups_normal_setup[#category][#whatever]%
+ \else
+ \strc_itemgroups_normal_setup[#category][\c!option={#whatever}]%
+ \fi}
+
+\def\strc_itemgroups_setup_list_level_a#category#whatever#level%
+ {\strc_itemgroups_normal_setup[#category:#level][#whatever]}
+
+\def\strc_itemgroups_setup_list_level_b#category#whatever#level%
+ {\strc_itemgroups_normal_setup[#category:#level][\c!option={#whatever}]}
+
+% \def\strc_itemgroups_setup_list#subcategories#category#whatever%
+% {\doifelseassignment{#whatever}
+% {\processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_a{#category}{#whatever}}}
+% {\processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_b{#category}{#whatever}}}}
+
+\def\strc_itemgroups_setup_list#subcategories#category#whatever%
+ {\ifcondition\validassignment{#whatever}%
+ \processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_a{#category}{#whatever}}%
+ \else
+ \processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_b{#category}{#whatever}}%
+ \fi}
+
+\def\strc_itemgroups_increment_item_counter
+ {\ifconditional\c_strc_itemgroups_sub \else
+ \ifconditional\c_strc_itemgroups_symbol \else % \ifx\strc_itemgroups_extra_symbol\empty
+ \strc_counters_increment_sub\v_strc_itemgroups_counter\currentitemlevel
+ \fi
+ \fi}
+
+\unexpanded\def\strc_itemgroups_insert_item_counter
+ {\ifconditional\c_strc_itemgroups_repeat
+ \ifcase\c_strc_itemgroups_nesting
+ % skip
+ \or
+ \strc_itemgroups_insert_item_counter_indeed % this could become an option
+ \else
+ \strc_itemgroups_insert_item_counter_indeed
+ \fi
+ \else
+ \strc_itemgroups_insert_item_counter_indeed
+ \fi}
+
+\def\strc_itemgroups_insert_item_counter_indeed % quite slow ... every time this setup .. but it
+ {\begingroup % can be optimized ... best move some to strc-num
+ \setupcounter
+ [\v_strc_itemgroups_counter]%
+ [\c!prefix=\itemgroupparameter\c!prefix,
+ \c!prefixstopper=\itemgroupparameter\c!prefixstopper,
+ \c!prefixseparatorset=\itemgroupparameter\c!prefixseparatorset,
+ \c!prefixconversion=\itemgroupparameter\c!prefixconversion,
+ \c!prefixconversionset=\itemgroupparameter\c!prefixseparatorset,
+ \c!prefixset=\itemgroupparameter\c!prefixset,
+ \c!prefixsegments=\itemgroupparameter\c!prefixsegments,
+ \c!prefixconnector=\itemgroupparameter\c!prefixconnector,
+ \c!criterium=\itemgroupparameter\c!criterium,
+ \c!numberorder=\ifconditional\c_strc_itemgroups_reverse\v!reverse\else\v!normal\fi,
+ \c!numberstopper=\expdoif{\itemgroupparameter\c!placestopper}\v!yes{\itemgroupparameter\c!stopper},
+ \c!numberconversionset=\v_strc_itemgroups_counter,
+ \c!numbersegments=\currentitemgroupsegments]%
+ % there will be a fixedconversion key
+ %\normalexpanded{\defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+ \normalexpanded{\strc_sets_define_conversion_set[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+ %
+ \convertedcounter[\v_strc_itemgroups_counter]% [\number\currentitemlevel]%
+ \strc_itemgroups_insert_reference
+ \endgroup}
+
+% needs testing (maybe it need to happen later)
+%
+% \appendtoks
+% \setupcounter
+% [\v_strc_itemgroups_counter]%
+% [\c!prefix=\itemgroupparameter\c!prefix,
+% \c!prefixstopper=\itemgroupparameter\c!prefixstopper,
+% \c!prefixseparatorset=\itemgroupparameter\c!prefixseparatorset,
+% \c!prefixconversion=\itemgroupparameter\c!prefixconversion,
+% \c!prefixconversionset=\itemgroupparameter\c!prefixseparatorset,
+% \c!prefixset=\itemgroupparameter\c!prefixset,
+% \c!prefixsegments=\itemgroupparameter\c!prefixsegments,
+% \c!prefixconnector=\itemgroupparameter\c!prefixconnector,
+% \c!criterium=\itemgroupparameter\c!criterium,
+% \c!numberorder=\ifconditional\c_strc_itemgroups_reverse\v!reverse\else\v!normal\fi,
+% \c!numberstopper=\expdoif{\itemgroupparameter\c!placestopper}\v!yes{\itemgroupparameter\c!stopper},
+% \c!numberconversionset=\v_strc_itemgroups_counter,
+% \c!numbersegments=\currentitemgroupsegments]%
+% \to\itemgroupcommands
+%
+% \def\strc_itemgroups_insert_item_counter_indeed % quite slow ... every time this setup .. but it
+% {\begingroup % can be optimized ... best move some to strc-num
+% % there will be a fixedconversion key
+% %\normalexpanded{\defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+% \normalexpanded{\strc_sets_define_conversion_set[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+% %
+% \convertedcounter[\v_strc_itemgroups_counter]% [\number\currentitemlevel]%
+% \strc_itemgroups_insert_reference
+% \endgroup}
+
+\def\strc_itemgroups_set_symbol#symbol%
+ {\edef\strc_itemgroups_tmp_symbol{#symbol}%
+ \ifx\strc_itemgroups_tmp_symbol\empty \else
+ \doifelsesymboldefined\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_set_symbol_symbol
+ {\doifelseconversiondefined\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_set_symbol_conversion
+ \donothing}%
+ \fi}
+
+\def\strc_itemgroups_set_symbol_symbol
+ {\let\currentitemgroupsymbol\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_store_global_symbol\currentitemgroupsymbol
+ \strc_itemgroups_store_local_symbol\v_strc_itemgroups_unknown_symbol
+ \let\strc_itemgroups_used_symbol\strc_itemgroups_set_symbol_symbol_item
+ \let\strc_itemgroups_asked_symbol\empty}
+
+\def\strc_itemgroups_set_symbol_conversion
+ {\let\currentitemgroupsymbol\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_store_global_symbol\currentitemgroupsymbol
+ \strc_itemgroups_store_local_symbol\strc_itemgroups_insert_item_counter
+ \let\strc_itemgroups_used_symbol\strc_itemgroups_set_symbol_conversion_item
+ \let\strc_itemgroups_asked_symbol\empty}
+
+\def\strc_itemgroups_set_symbol_symbol_item
+ {\symbol[\currentitemgroupsymbol]}
+
+\def\strc_itemgroups_set_symbol_conversion_item
+ {\ifconditional\c_strc_itemgroups_text
+ % maybe block stopper here, but one can as well clone an itemgroup then
+ \itemgroupparameter\c!lefttext
+ \strc_itemgroups_fetch_local_symbol
+ \itemgroupparameter\c!righttext
+ \else
+ \itemgroupparameter\c!left
+ \strc_itemgroups_fetch_local_symbol
+ \itemgroupparameter\c!right
+ \fi}
+
+\def\strc_itemgroups_calculate_list_width#level%
+ {\let\savedcurrentitemgroup\currentitemgroup
+ \edef\currentitemgroup{\currentparentitemgroup:\number#level}%
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \d_strc_itemgroups_list_width\d_strc_itemgroups_max_width
+ \orelse\ifnum\itemgroupparameter\c!factor>\zerocount
+ \d_strc_itemgroups_list_width\itemgroupparameter\c!step\relax
+ \ifdim\d_strc_itemgroups_list_width=\zeropoint \d_strc_itemgroups_list_width=.5em\fi
+ \multiply\d_strc_itemgroups_list_width \itemgroupparameter\c!factor
+ \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!width\relax
+ \else
+ \d_strc_itemgroups_list_width\itemgroupparameter\c!width\relax
+ \fi
+ \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!distance\relax
+ \let\currentitemgroup\savedcurrentitemgroup}
+
+\unexpanded\def\startitemgroup
+ {\dotripleempty\strc_itemgroups_start}
+
+\def\strc_itemgroups_start[#category][#options][#settings]%
+ {\begingroup % (1)
+ \def\currentitemgroup{#category}% no nested mixing of itemgroups
+ \let\currentparentitemgroup\currentitemgroup
+ \global\advance\c_strc_itemgroups_nesting\plusone
+ \def\currentitemlevel{\number\c_strc_itemgroups_nesting}%
+ \normalexpanded{\chaintocurrentitemgroup{\currentparentitemgroup:\currentitemlevel}}%
+ \edef\currentitemgroup{\currentparentitemgroup:\currentitemlevel}%
+ %
+ \ifthirdargument
+ \strc_itemgroups_start_indeed[#options][#settings]%
+ \orelse\ifsecondargument
+ \ifcondition\validassignment{#options}%
+ \strc_itemgroups_start_indeed[][#options]%
+ \else
+ \strc_itemgroups_start_indeed[#options][]%
+ \fi
+ \else
+ \strc_itemgroups_start_indeed[][]%
+ \fi}
+
+\def\strc_itemgroups_start_indeed[#options][#settings]%
+ {\edef\itemgroupoptions{\itemgroupparameter\c!option}%
+ \edef\itemgroupextraoptions{#options}%
+ \ifx\itemgroupoptions\empty
+ \let\itemgroupoptions\itemgroupextraoptions
+ \orelse\ifx\itemgroupextraoptions\empty
+ % ok
+ \else
+ \edef\itemgroupoptions{\itemgroupoptions,\itemgroupextraoptions}%
+ \fi
+ \begingroup % (2)
+ \the\itemgroupcommands
+ \let\c_strc_itemgroups_text_saved\c_strc_itemgroups_text
+ \strc_itemgroups_initialize_local
+ \strc_itemgroups_preset_stage_one\itemgroupoptions
+%
+% \ifhmode
+% \ifconditional\c_strc_itemgroups_auto_concat
+% \ifdim\lastskip=\d_strc_itemgroups_signal
+% \settrue\c_strc_itemgroups_concat
+% \fi
+% \fi
+% \ifconditional\c_strc_itemgroups_text_saved \else
+% \ifconditional\c_strc_itemgroups_text \else
+% \par
+% \fi
+% \fi
+% \fi
+%
+ \iftrialtypesetting
+ \strc_counters_save\v_strc_itemgroups_counter
+ \fi
+ \c_strc_itemgroups_n_of_items\zerocount
+ \strc_itemgroups_check_n_of_items
+ \ifx\itemgroupoptions\empty
+ \strc_itemgroups_setup_symbol_default
+ \strc_itemgroups_reset_continue_state
+ \setupcurrentitemgroup[#settings]%
+ \else
+ \strc_itemgroups_process_options\itemgroupoptions
+ \setupcurrentitemgroup[#settings]%
+ \ifconditional\c_strc_itemgroups_continue
+ \strc_itemgroups_setup_symbol_continue
+ \strc_itemgroups_fetch_continue_state
+ \else
+ \strc_itemgroups_setup_symbol_asked
+ \strc_itemgroups_store_continue_state\itemgroupoptions{#settings}%
+ \fi
+ \fi
+ %
+ \ifhmode
+ \ifconditional\c_strc_itemgroups_auto_concat
+ \ifdim\lastskip=\d_strc_itemgroups_signal
+ \settrue\c_strc_itemgroups_concat
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_text_saved \else
+ \ifconditional\c_strc_itemgroups_text \else
+ \par
+ \fi
+ \fi
+ \fi
+ %
+ \ifnum\c_strc_itemgroups_nesting=\plusone % NIEUW
+ \doadaptleftskip {\itemgroupparameter\c!margin}%
+ \doadaptleftskip {\itemgroupparameter\c!leftmargin}%
+ \doadaptrightskip{\itemgroupparameter\c!rightmargin}%
+ \fi
+ %
+ \doadaptleftskip {\itemgroupparameter\c!leftmargindistance}%
+ \doadaptrightskip{\itemgroupparameter\c!rightmargindistance}%
+ %
+ \usealignparameter\itemgroupparameter
+ \edef\m_strc_itemgroups_indenting{\itemgroupparameter\c!indenting}%
+ \ifnum\c_strc_itemgroups_nesting>\zerocount
+ \settrue\c_strc_itemgroups_first
+ \ifconditional\c_strc_itemgroups_continue \else
+ \strc_counters_restart_sub\v_strc_itemgroups_counter\currentitemlevel{\numexpr\itemgroupparameter\c!start-\plusone\relax}%
+ \fi
+ \fi
+ \ifx\strc_itemgroups_used_symbol\empty
+ \strc_itemgroups_set_symbol\strc_itemgroups_asked_symbol % ** default value
+ \ifx\strc_itemgroups_used_symbol\empty
+ \let\currentitemgroupsymbol\currentitemlevel % ** fall back
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_auto_intro\ifnum\prevgraf<\plusthree
+ \settrue\c_strc_itemgroups_intro
+ \fi\fi
+ \ifconditional\c_strc_itemgroups_paragraph
+ \ifnum\c_strc_itemgroups_nesting>\plusone
+ \letitemgroupparameter\c!inbetween\empty
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_pack
+ \letitemgroupparameter\c!inbetween\empty
+ \fi
+ \ifconditional\c_strc_itemgroups_columns
+ \ifinsidecolumns\else\ifcase\c_strc_itemgroups_column_depth
+ \global\c_strc_itemgroups_column_depth\c_strc_itemgroups_nesting % global ?
+ \strc_itemgroups_before_command
+ \strc_itemgroups_tag_start_group
+ \strc_itemgroups_start_columns
+ \fi\fi
+ \fi
+ \ifconditional\c_strc_itemgroups_fitting
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \letitemgroupparameter\c!width\d_strc_itemgroups_max_width
+ \fi
+ \fi
+ \strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \ifdim\d_strc_itemgroups_list_width>\zeropoint\relax
+ \ifconditional\c_strc_itemgroups_inline\else
+ \advance\leftskip\d_strc_itemgroups_list_width\relax
+ \fi
+ \fi
+ \ifx\m_strc_itemgroups_repeat_start\empty
+ \let\currentitemgroupconversionset \currentitemgroupsymbol
+ \edef\currentitemgroupsegments {\currentitemlevel}%
+ \else
+ \edef\currentitemgroupconversionset{\currentitemgroupconversionset,\currentitemgroupsymbol}%
+ \edef\currentitemgroupsegments {\m_strc_itemgroups_repeat_start:\currentitemlevel}%
+ \fi
+ \d_strc_itemgroups_asked_width\itemgroupparameter\c!width\relax
+ \startcollectitems}
+
+\let\startcollectitems\relax
+\let\stopcollectitems \relax
+
+\letvalue{\??itemgroupalign\v!flushleft }\relax
+\letvalue{\??itemgroupalign\v!right }\relax
+\letvalue{\??itemgroupalign\v!flushright}\hfill
+\letvalue{\??itemgroupalign\v!left }\hfill
+\letvalue{\??itemgroupalign\v!middle }\hfil
+\letvalue{\??itemgroupalign\v!center }\hfil
+
+\def\strc_itemgroups_left_sym_filler
+ {\csname\??itemgroupalign\itemgroupparameter\c!symalign\endcsname}
+
+% symbols + states
+
+\def\strc_itemgroups_store_global_symbol#symbol%
+ {\letgvalue{\??itemgroupglobal\currentitemlevel}#symbol}
+
+\def\strc_itemgroups_store_local_symbol#symbol%
+ {\letgvalue{\??itemgrouplocal\currentitemlevel}#symbol}
+
+\def\strc_itemgroups_fetch_global_symbol
+ {\csname\??itemgroupglobal\currentitemlevel\endcsname}
+
+\def\strc_itemgroups_fetch_local_symbol
+ {\csname\??itemgrouplocal\currentitemlevel\endcsname}
+
+\def\strc_itemgroups_setup_symbol_default
+ {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}%
+ \strc_itemgroups_store_global_symbol\empty}
+
+\def\strc_itemgroups_setup_symbol_continue
+ {\ifcsname\??itemgroupglobal\currentitemlevel\endcsname
+ \let\strc_itemgroups_asked_symbol\strc_itemgroups_fetch_global_symbol
+ \else
+ \let\strc_itemgroups_asked_symbol\currentitemlevel
+ \fi}
+
+\def\strc_itemgroups_setup_symbol_asked
+ {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}}
+
+\ifdefined\strc_itemgroups_start_columns
+
+ % already defined in page-mix
+
+\else
+
+ % will be redefined in page-mix
+
+ \ifdefined\startcolumns \else
+ \unexpanded\def\startcolumns[#settings]{}
+ \unexpanded\def\stopcolumns {}
+ \fi
+
+ \def\strc_itemgroups_start_columns
+ {\startcolumns
+ [\c!n=\itemgroupparameter\c!n,
+ \c!height=,
+ \c!rule=\v!off,
+ \c!balance=\v!yes,
+ \c!align=\v!no]}
+
+ \def\strc_itemgroups_stop_columns
+ {\stopcolumns}
+
+\fi
+
+\unexpanded\def\stopitemgroup
+ {\stopcollectitems
+ \ifconditional\c_strc_itemgroups_text
+ \removeunwantedspaces
+ \space
+ \ignorespaces
+ \else
+ \par
+ \fi
+ \strc_itemgroups_register_status
+ \ifconditional\c_strc_itemgroups_first \else
+ \dostoptagged
+ \dostoptagged
+ % \endgroup % (3)
+ \fi
+ \ifnum\c_strc_itemgroups_column_depth=\c_strc_itemgroups_nesting\relax
+ \strc_itemgroups_stop_columns
+ \global\c_strc_itemgroups_column_depth\zerocount % global ?
+ \strc_itemgroups_tag_stop_group
+ \strc_itemgroups_after_command
+ \dontrechecknextindentation
+ \orelse\ifnum\c_strc_itemgroups_nesting=\plusone
+ \strc_itemgroups_insert_breakallow
+ \strc_itemgroups_tag_stop_group
+ \strc_itemgroups_after_command
+ \useindentnextparameter\itemgroupparameter
+ \else
+ % nieuw, not yet nobreak handling
+ \strc_itemgroups_tag_stop_group
+ \ifcase\c_strc_itemgroups_spacing_mode
+ \strc_itemgroups_after_command
+ \or
+ \strc_itemgroups_after_command
+ \fi
+ \dontrechecknextindentation
+ \fi
+ % new test, needed in sidefloats (surfaced in volker's proceedings)
+ \iftrialtypesetting
+ \strc_counters_restore\v_strc_itemgroups_counter % could happen in LUA
+ \fi
+ \global\advance\c_strc_itemgroups_nesting\minusone
+ \xdef\currentitemlevel{\number\c_strc_itemgroups_nesting}%
+ %\ifconditional\c_strc_itemgroups_text
+ \endgroup % (2)
+ \endgroup % (1)
+ %\else
+ % \endgroup % (2)
+ % \endgroup % (1)
+ % \par % hm, already done, and dangerous as \c_strc_itemgroups_text is already forgotten
+ %\fi
+ \dorechecknextindentation}
+
+% The items.
+
+\unexpanded\def\startitemgroupitem
+ {\dosingleempty\strc_itemgroups_start_item}
+
+\def\strc_itemgroups_start_item_first
+ {\setfalse\c_strc_itemgroups_first
+ % \begingroup % (3)
+ \ifcase\c_strc_itemgroups_nesting
+ % 0
+ \or
+ \strc_itemgroups_start_item_first_one % 1
+ \else
+ \strc_itemgroups_start_item_first_two % 2+
+ \fi}
+
+\def\strc_itemgroups_start_item_first_one
+ {\ifcase\c_strc_itemgroups_column_depth
+ \ifconditional\c_strc_itemgroups_intro\strc_itemgroups_insert_breakno\fi
+ \strc_itemgroups_before_command
+ \strc_itemgroups_tag_start_group
+ \ifconditional\c_strc_itemgroups_intro\strc_itemgroups_insert_breakno\fi
+ \fi}
+
+\def\strc_itemgroups_start_item_first_two
+ {\ifconditional\c_strc_itemgroups_paragraph\else
+ \edef\previtemlevel{\the\numexpr\c_strc_itemgroups_nesting-\plusone}%
+ \ifcase\c_strc_itemgroups_spacing_mode
+ \strc_itemgroups_before_command
+ \or
+ \doifelsenothing\strc_itemgroups_before_command % should possibly expand to empty
+ {\nameditemgroupparameter{\currentparentitemgroup:\previtemlevel}\c!inbetween}%
+ \strc_itemgroups_before_command
+ \else
+ \nameditemgroupparameter{\currentparentitemgroup:\previtemlevel}\c!inbetween
+ \fi
+ \strc_itemgroups_tag_start_group
+ \fi}
+
+\def\strc_itemgroups_start_item_next
+ {\dostoptagged % ok? what do we stop here?
+ \dostoptagged % ok? what do we stop here?
+ \ifconditional\c_strc_itemgroups_text
+ \ifhmode
+ % WS: make the distance between items customizable, think about better default values -> see itemize-1.tex
+ \strc_itemgroups_set_text_item_distance% HH: moved out and made configurable (sort of)
+ \removeunwantedspaces
+ \hskip\m_strc_itemgroups_text_distance\relax
+ \fi
+ \else
+ \strc_itemgroups_between_command
+ \fi}
+
+% c_strc_itemgroups_concat:
+%
+% the problem is that we use leftskip so concat cannot reliable take the height into
+% account; it's .. rather tricky when white space in there anyway (due to \par) .. so
+% we rely on a special blank method
+%
+% \startitemize[n]
+% \item bla
+% \item \startitemize[a]
+% \item bla $\displaystyle\int^{x^{y^4}}$ \item bla
+% \stopitemize
+% \stopitemize
+
+\unexpanded\def\strc_itemgroups_start_item[#reference]% we can reuse more
+ {\def\currentitemreference{#reference}%
+ \ifconditional\c_strc_itemgroups_text
+ % begin of item
+ \else
+ \par
+ \fi
+ \ifconditional\c_strc_itemgroups_concat
+ \strc_itemgroups_insert_breakno
+ \fi
+ \strc_itemgroups_increment_item_counter
+ \ifconditional\c_strc_itemgroups_first
+ \strc_itemgroups_start_item_first
+ \else
+ \strc_itemgroups_start_item_next
+ \fi
+ \ifconditional\c_strc_itemgroups_concat
+ \spac_overlay_lines % see spac-ver.mkvi ... a typical potential problem
+ \setfalse\c_strc_itemgroups_concat
+ \fi
+ \dostarttagged\t!item\empty
+ % \dotagsetitem\empty
+ \dostarttagged\t!itemtag\empty
+ \strc_itemgroups_insert_item
+ \dostoptagged
+ \ifconditional\c_strc_itemgroups_pack
+ \setupwhitespace[\v!none]%
+ \fi
+ \itemgroupparameter\c!inner % will become obsolete (better use setups)
+ \strc_itemgroups_margin_symbol
+ \let\strc_itemgroups_margin_symbol\relax
+ \dostarttagged\t!itemcontent\empty
+ \begstrut % \strut
+ \nobreak % else problems with intext items
+ \seteffectivehsize % NEW !
+ \hskip\d_strc_itemgroups_signal % concat
+ \itemgroupparameter\c!command}
+
+\unexpanded\def\stopitemgroupitem
+ {\ifhmode
+ \endstrut % new per 2017-12-15
+ \fi
+ \ifconditional\c_strc_itemgroups_text
+ % nothing
+ \else
+ \endgraf
+ \fi}
+\unexpanded\def\startitemgrouphead
+ {\dosingleempty\strc_itemgroups_start_head}
+
+\unexpanded\def\strc_itemgroups_start_head[#reference]%
+ {\ifconditional\c_strc_itemgroups_first \else
+ \strc_itemgroups_insert_breakallow
+ \fi
+ \ifconditional\c_strc_itemgroups_pack \else
+ \strc_itemgroups_before_head_command
+ \fi
+ \ifconditional\c_strc_itemgroups_first
+ \ifconditional\c_strc_itemgroups_intro \else
+ \ifcase\c_strc_itemgroups_nesting
+ \strc_itemgroups_insert_breakallow
+ \fi
+ \fi
+ \fi
+ \strc_itemgroups_start_item[#reference]%
+ \pickupgroupedcommand
+ \strc_itemgroups_start_head_indeed
+ \strc_itemgroups_stop_head_indeed
+ \strc_itemgroups_head_body_indeed}
+
+\unexpanded\def\stopitemgrouphead
+ {\dostoptagged
+ \stopitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_head_indeed
+ {\settrue\c_strc_itemgroups_head
+ \dotagsetitem\s!head% % weird place
+ \dostarttagged\t!itemhead\empty
+ \useitemgroupstyleandcolor\c!headstyle\c!headcolor\ignorespaces}
+
+\unexpanded\def\strc_itemgroups_stop_head_indeed
+ {\removeunwantedspaces
+ \dostoptagged
+ \ifconditional\c_strc_itemgroups_text
+ \space
+ \ignorespaces
+ \else
+ \par
+ \fi
+ \strc_itemgroups_insert_breakno
+ \ifconditional\c_strc_itemgroups_pack\else\strc_itemgroups_after_head_command\fi
+ \strc_itemgroups_insert_breakno}
+
+\unexpanded\def\strc_itemgroups_head_body_indeed
+ {\dostarttagged\t!itembody\empty
+ \noindentation}
+
+% Simple commands.
+
+\unexpanded\def\strc_itemgroups_start_do_item
+ {\startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_no_item
+ {\let\currentitemreference\empty
+ \strc_itemgroups_increment_item_counter
+ %\advance\c_strc_itemgroups_n_of_items\plusone
+ \setbox\b_strc_itemgroups\emptyhbox
+ \strc_itemgroups_check_for_repeated
+ \ignorespaces}
+
+\unexpanded\def\strc_itemgroups_start_button[#destination]%
+ {\edef\m_strc_itemgroups_destination{#destination}%
+ \startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_symbol#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
+ \startitemgroupitem
+ \dotagsetitem\s!symbol}
+
+\unexpanded\def\strc_itemgroups_start_dummy
+ {\strc_itemgroups_start_symbol
+ %\strut\strut} % two ?
+ \begstrut}
+
+\unexpanded\def\strc_itemgroups_start_subitem
+ {\settrue\c_strc_itemgroups_sub
+ \startitemgroupitem
+ \dotagsetitem\s!sub}
+
+\unexpanded\def\strc_itemgroups_start_edge#text%
+ {\strc_itemgroups_start_symbol
+ {\strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \dostarttagged\t!ignore\empty % for the moment, maybe an attribute
+ \hbox to \d_strc_itemgroups_list_width
+ {#text\hskip\itemgroupparameter\c!distance}%
+ \dostoptagged}}
+
+\unexpanded\def\strc_itemgroups_start_margin#text%
+ {\def\strc_itemgroups_margin_symbol % brrr
+ {\dostarttagged\t!ignore\empty % for the moment, maybe an attribute
+ \llap
+ {\begingroup
+ \useitemgroupstyleandcolor\c!marstyle\c!marcolor
+ #text% keep em/ex local
+ \endgroup
+ \hskip\dimexpr\leftskip+\leftmargindistance\relax}%
+ \dostoptagged}%
+ \startitemgroupitem
+ \dotagsetitem\s!margin}
+
+\unexpanded\def\strc_itemgroups_start_text#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
+ \settrue\c_strc_itemgroups_txt
+ \startitemgroupitem}
+
+% \unexpanded\def\strc_itemgroups_start_head
+% {\settrue\c_strc_itemgroups_head
+% \startitemgrouphead}
+
+\unexpanded\def\strc_itemgroups_start_items
+ {\dosingleempty\strc_itemgroups_start_items_indeed}
+
+\unexpanded\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost
+ {\strc_itemgroups_start_edge
+ {\dorecurse{0\itemgroupparameter\c!items}{\strc_itemgroups_used_symbol\hss}%
+ \unskip}}
+
+% \unexpanded\def\startspecialitemgroupitem[#name]%
+% {\csname\??itemgroupstart\ifcsname\??itemgroupstart#name\endcsname#name\else\v!item\fi\endcsname}
+
+\unexpanded\def\startspecialitemgroupitem[#name]%
+ {\ifcsname\??itemgroupstart#name\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\strc_itemgroups_start_do_item
+ \fi}
+
+\unexpanded\def\stopspecialitemgroupitem
+ {\stopitemgroupitem}
+
+\letvalue{\??itemgroupstart\v!item}\strc_itemgroups_start_do_item
+\letvalue{\??itemgroupstart\v!sub }\strc_itemgroups_start_subitem
+\letvalue{\??itemgroupstart\v!sym }\strc_itemgroups_start_symbol
+\letvalue{\??itemgroupstart\v!ran }\strc_itemgroups_start_edge
+\letvalue{\??itemgroupstart\v!its }\strc_itemgroups_start_items
+\letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin
+
+\def\optimizelistitemsbreak
+ {\ifcase\c_strc_itemgroups_column_depth
+ \ifconditional\c_strc_itemgroups_optimize
+ \ifcase\c_strc_itemgroups_max_items
+ \orelse\ifnum\c_strc_itemgroups_max_items=\plusthree
+ \ifnum\c_strc_itemgroups_n_of_items>\plusone
+ \strc_itemgroups_insert_nobreak
+ \fi
+ \orelse\ifnum\c_strc_itemgroups_max_items>\plusthree
+ \ifnum\c_strc_itemgroups_n_of_items=\plustwo
+ \ifconditional\c_strc_itemgroups_intro
+ \strc_itemgroups_insert_breakno
+ \else
+ \strc_itemgroups_insert_nobreak
+ \fi
+ \orelse\ifnum\c_strc_itemgroups_max_items=\c_strc_itemgroups_n_of_items\relax
+ \strc_itemgroups_insert_nobreak
+ \orelse\ifnum\c_strc_itemgroups_n_of_items>\plustwo
+ \strc_itemgroups_insert_break
+ \else
+ \ifconditional\c_strc_itemgroups_intro\else\strc_itemgroups_insert_break\fi
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\def\strc_itemgroups_handle_text_item
+ {\scratchdimen\wd\b_strc_itemgroups
+ \advance \scratchdimen \itemgroupparameter\c!distance\relax
+ \ifdim\scratchdimen>\d_strc_itemgroups_list_width
+ \advance\scratchdimen -\d_strc_itemgroups_list_width
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \llap{\hbox to \d_strc_itemgroups_list_width{\ifconditional\c_strc_itemgroups_sub\llap{+\enspace}\fi\box\b_strc_itemgroups\hss}}% was: \hfill
+ \hskip\scratchdimen}
+
+\def\strc_itemgroups_handle_lapped_item_positive
+ {\llap
+ {\dontcomplain
+ \hbox to \d_strc_itemgroups_list_width
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ \llap{+\enspace}%
+ \dostoptagged
+ \fi
+ \strc_itemgroups_left_sym_filler
+ \box\b_strc_itemgroups % can already have a forced widt, only factor handled here
+ \hfil
+ \hskip\itemgroupparameter\c!distance}}}
+
+\def\strc_itemgroups_handle_lapped_item_negative
+ {\llap
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ \llap{+\enspace}%
+ \dostoptagged
+ \fi
+ \box\b_strc_itemgroups
+ \hskip\leftmargindistance}}
+
+\def\strc_itemgroups_handle_groups_text_item
+ {\hbox
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ +\enspace
+ \dostoptagged
+ \fi
+ \box\b_strc_itemgroups
+ \hskip\interwordspace}%
+ \nobreak}
+
+\def\strc_itemgroups_handle_groups_inline_item
+ {\hbox to \d_strc_itemgroups_list_width
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ \llap{+\enspace}%
+ \dostoptagged
+ \fi
+ \box\b_strc_itemgroups
+ \hss}} % was: \hfill
+
+\unexpanded\def\strc_itemgroups_start_head_sym#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
+ \settrue\c_strc_itemgroups_head
+ \strc_itemgroups_start_head}
+
+\def\strc_itemgroups_make_symbol_box
+ {\setbox\b_strc_itemgroups\autodirhbox
+ {\ifconditional\c_strc_itemgroups_head
+ \ifconditional\c_strc_itemgroups_symbol
+ \strc_itemgroups_insert_extra_reference
+ \useitemgroupstyleandcolor\c!symstyle\c!symcolor
+ \strc_itemgroups_extra_symbol
+ \else
+ \useitemgroupstyleandcolor\c!headstyle\c!headcolor
+ \strc_itemgroups_used_symbol
+ \fi
+ \else
+ \ifconditional\c_strc_itemgroups_symbol
+ \strc_itemgroups_insert_extra_reference
+ \useitemgroupstyleandcolor\c!symstyle\c!symcolor
+ \strc_itemgroups_extra_symbol
+ \else
+ \useitemgroupstyleandcolor\c!style\c!color
+ \strc_itemgroups_used_symbol
+ \fi
+ \fi}%
+ \let\strc_itemgroups_extra_symbol\empty
+ \setfalse\c_strc_itemgroups_symbol}
+
+\def\strc_itemgroups_make_fitting_box
+ {\ifdim\wd\b_strc_itemgroups>\itemgroupparameter\c!maxwidth\relax
+ \normalexpanded{\global\setitemgroupparameter{\c!maxwidth}{\the\wd\b_strc_itemgroups}}%
+ \fi
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \setbox\b_strc_itemgroups\simplealignedbox
+ {\dimexpr\d_strc_itemgroups_max_width+\itemgroupparameter\c!distance\relax}
+ {\itemgroupparameter\c!itemalign}
+ {\box\b_strc_itemgroups\hskip\itemgroupparameter\c!distance}%
+ \fi}
+
+\def\strc_itemgroups_make_aligned_box
+ {\doifsomething{\itemgroupparameter\c!itemalign}
+ {\setbox\b_strc_itemgroups\simplealignedbox
+ {\dimexpr\d_strc_itemgroups_asked_width+\itemgroupparameter\c!distance\relax}
+ {\itemgroupparameter\c!itemalign}
+ {\box\b_strc_itemgroups\hskip\itemgroupparameter\c!distance}}}
+
+\def\strc_itemgroups_make_destination_box
+ {\iftrialtypesetting \else \ifx\m_strc_itemgroups_destination\empty \else
+ \setbox\b_strc_itemgroups\hbox{\directgotobox{\box\b_strc_itemgroups}[\m_strc_itemgroups_destination]}%
+ \fi\fi}
+
+\def\strc_itemgroups_check_indenting
+ {\setfalse\c_strc_itemgroups_indented_first
+ \ifx\m_strc_itemgroups_indenting\empty \else
+ \normalexpanded{\setupindenting[\v!reset,\v!yes,\m_strc_itemgroups_indenting]}%
+ \ifconditional\c_spac_indentation_indent_first % better is to have a mode
+ \doifnot{\itemgroupparameter\c!alignsymbol}\v!yes
+ {\settrue\c_strc_itemgroups_indented_first}%
+ \fi
+ \fi}
+
+\def\strc_itemgroups_check_for_repeated
+ {\ifconditional\c_strc_itemgroups_repeat
+ \ifx\m_strc_itemgroups_repeat_start\empty
+ \edef\m_strc_itemgroups_repeat_start{\currentitemlevel}%
+ \fi
+ \else
+ \let\m_strc_itemgroups_repeat_start\empty
+ \fi}
+
+\def\strc_itemgroups_insert_item
+ {\ifconditional\c_strc_itemgroups_text % again?
+ % begin of item
+ \else
+ \par % done twice?
+ \fi
+ \advance\c_strc_itemgroups_n_of_items\plusone
+ \optimizelistitemsbreak
+ \strc_itemgroups_check_indenting
+ \dontleavehmode
+ \ifconditional\c_strc_itemgroups_indented_first
+ \hskip-\parindent
+ \fi
+ \strc_itemgroups_make_symbol_box
+ \strc_itemgroups_make_destination_box
+ \ifconditional\c_strc_itemgroups_fitting
+ \strc_itemgroups_make_fitting_box
+ \else\ifdim\d_strc_itemgroups_asked_width>\zeropoint
+ \strc_itemgroups_make_aligned_box
+ \fi\fi
+ \let\m_strc_itemgroups_destination\empty
+ \ht\b_strc_itemgroups\strutheight % just in case a symbols is not yet available in
+ \dp\b_strc_itemgroups\strutdepth % the current run (more a mkii mp side artifact)
+ \strc_itemgroups_check_for_repeated
+ \ifdim\d_strc_itemgroups_asked_width<\zeropoint\relax
+ \strc_itemgroups_handle_lapped_item_negative
+ \else
+ \ifdim\d_strc_itemgroups_asked_width=\zeropoint\relax
+ \strc_itemgroups_calculate_list_width\plusone
+ \else
+ \strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \fi
+ \ifconditional\c_strc_itemgroups_text
+ \strc_itemgroups_handle_groups_text_item
+ \orelse\ifconditional\c_strc_itemgroups_inline
+ \strc_itemgroups_handle_groups_inline_item
+ \orelse\ifconditional\c_strc_itemgroups_txt
+ \strc_itemgroups_handle_text_item
+ \else
+ \strc_itemgroups_handle_lapped_item_positive
+ \fi
+ \fi
+ \setfalse\c_strc_itemgroups_head
+ \setfalse\c_strc_itemgroups_sub
+ \ifconditional\c_strc_itemgroups_indented_first
+ \hskip\parindent
+ \fi
+ \ignorespaces}
+
+\def\strc_itemgroups_start_item_nop
+ {\let\currentitemreference\empty
+ \strc_itemgroups_increment_item_counter
+ \advance\c_strc_itemgroups_n_of_items\plusone
+ \setbox\b_strc_itemgroups\hbox
+ {\useitemgroupstyleandcolor\c!style\c!color
+ \strc_itemgroups_used_symbol}%
+ \strc_itemgroups_check_for_repeated
+ \ignorespaces}
+
+\setvalue{\??itemgroupdistance\v!none}%
+ {\let\m_strc_itemgroups_text_distance\zeropoint}
+
+\setvalue{\??itemgroupdistance\v!space}%
+ {\def\m_strc_itemgroups_text_distance{\interwordspace\!!plus\interwordstretch\!!minus\interwordshrink}}
+
+\setvalue\??itemgroupdistance % catches empty value
+ {\let\m_strc_itemgroups_text_distance\zeropoint}
+
+\unexpanded\def\strc_itemgroups_set_text_item_distance
+ {\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}%
+ \ifx\m_strc_itemgroups_text_distance\empty
+ %
+ \orelse\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
+ \lastnamedcs
+ \else
+ \strc_itemgroups_set_text_item_distance_indeed
+ \fi}
+
+\def\strc_itemgroups_set_text_item_distance_indeed
+ {\assignvalue
+ \m_strc_itemgroups_text_distance
+ \m_strc_itemgroups_text_distance
+ {.5\interwordspace\!!plus.5\emwidth}%
+ {\interwordspace \!!plus \emwidth}%
+ {\emwidth \!!plus \interwordstretch\!!minus\interwordshrink}}
+
+% \unexpanded\def\strc_itemgroups_default_command
+% {\EveryPar{\ignorespaces}% needed ?
+% \ignorespaces}
+
+\unexpanded\def\strc_itemgroups_default_command
+ {\ignorespaces}
+
+%D Special case:
+
+\unexpanded\def\strc_itemgroups_head#text\par
+ {\startitemgrouphead{#text}}
+
+%D The local commands:
+
+\appendtoks
+ \let\item \strc_itemgroups_start_do_item
+ \let\noitem \strc_itemgroups_start_no_item
+ \let\itm \strc_itemgroups_start_do_item
+ \let\but \strc_itemgroups_start_button
+ \let\nop \strc_itemgroups_start_dummy
+ \let\txt \strc_itemgroups_start_text
+ \let\head \strc_itemgroups_head
+ \let\headsym \strc_itemgroups_start_head_sym
+ \let\startitem \startitemgroupitem
+ \let\stopitem \stopitemgroupitem
+ \let\starthead \startitemgrouphead
+ \let\stophead \stopitemgroupitemhead
+ \let\startspecialitem\startspecialitemgroupitem
+ \let\stopspecialitem \stopspecialitemgroupitem
+\to \itemgroupcommands
+
+\ifx\currentinterface \v!english \else
+
+ \appendtoks
+ \expandafter\let\csname\v!item \endcsname\strc_itemgroups_start_do_item
+ \expandafter\let\csname\v!sub \endcsname\strc_itemgroups_start_subitem
+ \expandafter\let\csname\v!sym \endcsname\strc_itemgroups_start_symbol
+ \expandafter\let\csname\v!ran \endcsname\strc_itemgroups_start_edge
+ \expandafter\let\csname\v!head \endcsname\strc_itemgroups_head
+ \expandafter\let\csname\v!its \endcsname\strc_itemgroups_start_items
+ \expandafter\let\csname\v!mar \endcsname\strc_itemgroups_start_margin
+ \expandafter\let\csname\v!txt \endcsname\strc_itemgroups_start_text
+ \expandafter\let\csname\e!start\v!item\endcsname\startitemgroupitem
+ \expandafter\let\csname\e!stop \v!item\endcsname\stopitemgroupitem
+ \expandafter\let\csname\e!start\v!head\endcsname\startitemgrouphead
+ \expandafter\let\csname\e!stop \v!head\endcsname\stopitemgrouphead
+ \to \itemgroupcommands
+
+\fi
+
+\relaxvalueifundefined \v!item
+\relaxvalueifundefined \v!sub
+\relaxvalueifundefined \v!sym
+\relaxvalueifundefined \v!ran
+\relaxvalueifundefined \v!head
+\relaxvalueifundefined \v!its
+\relaxvalueifundefined \v!mar
+\relaxvalueifundefined \v!txt
+\relaxvalueifundefined {\e!start\v!item}
+\relaxvalueifundefined {\e!stop \v!item}
+\relaxvalueifundefined {\e!start\v!head}
+\relaxvalueifundefined {\e!stop \v!head}
+
+%D A nice example of a plugin:
+%D
+%D \startbuffer
+%D \startitemize[a,random,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D
+%D \startitemize[a,random,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D
+%D \startitemize[a,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% better collectitems als conditional and a real plugin mechanism (some day)
+
+\newcount\c_strc_itemgroups_collected_stored
+\newcount\c_strc_itemgroups_collected_done
+\newcount\c_strc_itemgroups_collected_current
+
+% \expandafter\def\expandafter\strc_itemgroups_collected_store\expandafter#\expandafter1\csname\e!stop\v!item\endcsname % use grabuntil
+% {\advance\c_strc_itemgroups_collected_stored\plusone
+% \setvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_stored}{\startitemgroupitem#1\stopitemgroupitem}}
+
+\let\strc_itemgroups_collected_store\relax
+
+\normalexpanded{\def\strc_itemgroups_collected_store#1\csname\e!stop\v!item\endcsname}%
+ {\advance\c_strc_itemgroups_collected_stored\plusone
+ \setvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_stored}{\startitemgroupitem#1\stopitemgroupitem}}
+
+\def\strc_itemgroups_collected_flush_randomize
+ {\collecteditemgroupitem}
+
+\def\strc_itemgroups_collected_flush_horizontal
+ {\begingroup
+ \scratchcounter\itemgroupparameter\c!n\relax
+ \ifnum\c_strc_itemgroups_collected_done>\plusone
+ \ifcase\modulonumber\scratchcounter\c_strc_itemgroups_collected_done\relax
+ % compensate for rounding errors
+ \hfill % \hskip\zeropoint plus \scaledpoint minus \scaledpoint
+ \allowbreak
+ \fi
+ \fi
+ \noindent % no \dontleavehmode
+ \hbox to \dimexpr\availablehsize/\scratchcounter\relax{\collecteditemgroupitem\hss}%
+ \endgroup}
+
+% \def\strc_itemgroups_collected_flush_indeed
+% {\collecteditemgroupitem
+% \iftrialtypesetting
+% \undefinevalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
+% \fi}
+
+\def\strc_itemgroups_collected_flush_indeed
+ {\collecteditemgroupitem
+ \undefinevalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}}
+
+\def\strc_itemgroups_collected_flush
+ {\ifconditional\c_strc_itemgroups_randomize
+ \getrandomcount\c_strc_itemgroups_collected_current\plusone\c_strc_itemgroups_collected_stored
+ \else
+ \advance\c_strc_itemgroups_collected_current\plusone
+ \fi
+ \ifcsname\??itemgroupstack\number\c_strc_itemgroups_collected_current\endcsname
+ \edef\collecteditemgroupitem{\lastnamedcs}%
+ \ifconditional\c_strc_itemgroups_horizontal
+ \strc_itemgroups_collected_flush_horizontal
+ \else
+ \strc_itemgroups_collected_flush_indeed
+ \fi
+ \advance\c_strc_itemgroups_collected_done\plusone
+ \fi
+ \ifnum\c_strc_itemgroups_collected_done<\c_strc_itemgroups_collected_stored
+ \expandafter\strc_itemgroups_collected_flush
+ \fi}
+
+\unexpanded\def\stopcollectitems
+ {\ifconditional\c_strc_itemgroups_collecting
+ \c_strc_itemgroups_collected_done \zerocount
+ \c_strc_itemgroups_collected_current\zerocount
+ \ifnum\c_strc_itemgroups_collected_stored>\zerocount
+ \ifconditional\c_strc_itemgroups_horizontal
+ \strc_itemgroups_before_command
+ \setfalse\c_strc_itemgroups_first
+ \strc_itemgroups_collected_flush
+ %\strc_itemgroups_after_command % triggered elsewhere
+ \else
+ \strc_itemgroups_collected_flush
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\startcollectitems
+ {\ifconditional\c_strc_itemgroups_collecting
+ \c_strc_itemgroups_collected_stored\zerocount
+ \letvalue{\e!start\v!item}\strc_itemgroups_collected_store
+ \fi}
+
+%D Left-overs:
+
+\unexpanded\def\item
+ {\strc_itemgroups_item_alone}
+
+\def\strc_itemgroups_item_alone[#category]#text\par
+ {\doifelsesomething{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}%
+ \startitem#text\stopitem
+ \stopitemgroup}
+
+\unexpanded\def\head
+ {\strc_itemgroups_head_alone}
+
+\def\strc_itemgroups_head_alone[#category]#head\par#body\par
+ {\doifelsesomething{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}%
+ \starthead{#head}#body\stophead
+ \stopitemgroup}
+
+\setuvalue{\e!start\v!item}%
+ {\startitemgroup[\v!itemize]%
+ \startitemgroupitem
+ \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}}
+
+% \def\sym#text%
+% {\noindent
+% \begingroup
+% \setbox\scratchbox\hbox{\settrialtypesetting#text}%
+% \setbox\scratchbox\hbox\ifdim\wd\scratchbox<1em to 1.5\else spread 1\fi em{#text\hfil}%
+% \normalexpanded{\box\scratchbox\endgroup\hangindent\the\wd\scratchbox}%
+% \ignorespaces}
+
+%D End of plugin.
+
+%D Something for tables:
+
+\unexpanded\def\itemtag
+ {\dosingleempty\strc_itemgroups_item_tag}
+
+\unexpanded\def\strc_itemgroups_item_tag[#reference]% we can reuse more
+ {\def\currentitemreference{#reference}%
+ \iftrialtypesetting
+ \strc_counters_save\v_strc_itemgroups_counter
+ \strc_itemgroups_increment_item_counter
+ \strc_itemgroups_insert_item_tag_indeed
+ \strc_counters_restore\v_strc_itemgroups_counter
+ \else
+ \strc_itemgroups_increment_item_counter
+ \strc_itemgroups_insert_item_tag_indeed
+ \fi}
+
+\def\strc_itemgroups_insert_item_tag_indeed
+ {\letitemgroupparameter\c!distance\zeropoint
+ %letitemgroupparameter\c!width\zeropoint
+ \strc_itemgroups_make_symbol_box
+ \strc_itemgroups_make_destination_box
+ \let\m_strc_itemgroups_destination\empty
+ \ht\b_strc_itemgroups\strutheight
+ \dp\b_strc_itemgroups\strutdepth
+ \box\b_strc_itemgroups
+ \ignorespaces}
+
+%D Done again.
+
+\setupitemgroup
+ [\c!margin=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!leftmargindistance=\zeropoint,
+ \c!rightmargindistance=\zeropoint,
+ \c!indentnext=\v!yes,
+ \c!width=1.5\emwidth,
+ \c!factor=0,
+ %\c!distance=.5em, % is now:
+ \c!step=.5\emwidth, % deals with broad
+ \c!distance=\zeropoint,
+ %\c!align=\v!normal, % definitely not \v!normal !
+ %\c!symalign=,
+ %\c!color=,
+ %\c!indenting=, % untouched if empty
+ %\c!style=,
+ \c!marstyle=\v!type,
+ %\c!symstyle=,
+ %\c!headstyle=,
+ %\c!marcolor=,
+ %\c!symcolor=,
+ %\c!headcolor=,
+ %\c!beforehead=,
+ \c!symcolor=\itemgroupparameter\c!color, % new per 2012.01.17
+ \c!symstyle=\itemgroupparameter\c!style, % new per 2012.01.17
+ \c!afterhead=\blank,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ %\c!stopper=.,
+ \c!placestopper=\v!yes,
+ \c!stopper=.,
+ %\c!inner=,
+ \c!n=2,
+ \c!items=4,
+ \c!levels=10,
+ \c!lefttext=(,
+ \c!righttext=),
+ \c!start=1,
+ \c!criterium=\v!all, % permits 0 and negative numbers
+ %\c!option=,
+ \c!textdistance=\v!space, % none big medium small <dimension>
+ \c!command=\strc_itemgroups_default_command,
+ \c!indenting=\v!next,
+ %\c!alignsymbol=v!no,
+ \c!symbol=\currentitemlevel,
+ \c!prefix=\v!no,
+ %\c!prefixstopper=.,
+ %\c!prefixseparatorset=,
+ %\c!prefixconversion=,
+ %\c!prefixconversionset=,
+ %\c!prefixset=,
+ %\c!prefixsegments=1:100,
+ \c!prefixconnector=.,
+ \c!numberseparatorset=,
+ \c!numberconversionset=,
+ \c!numberstopper=.,
+ \c!numbersegments=1]
+
+\defineitemgroup
+ [\v!itemize]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-itm.mkvi b/tex/context/base/mkiv/strc-itm.mkvi
index eea42f2de..892e33104 100644
--- a/tex/context/base/mkiv/strc-itm.mkvi
+++ b/tex/context/base/mkiv/strc-itm.mkvi
@@ -15,14 +15,14 @@
\registerctxluafile{strc-itm}{}
-%D As we analyze/register widths and such we could as well push and pop the
-%D numbers at the \LUA\ end (which saves a few calls).
-
-%D Cleaning up this module happened around the time when Kate Bush came up
-%D with the nicest numbered list of words: 50 Words For Snow. It's therefore
-%D no surprise that I had that cd running several times when updating this
-%D code. One of the highlights of 2011.
-
+%D As we analyze/register widths and such we could as well push and pop the numbers
+%D at the \LUA\ end (which saves a few calls).
+%D
+%D Cleaning up this module happened around the time when Kate Bush came up with the
+%D nicest numbered list of words: 50 Words For Snow. It's therefore no surprise that
+%D I had that cd running several times when updating this code. One of the
+%D highlights of 2011.
+%D
%D This module needs to be rewritten but that is tricky with respect to
%D compatibilitity. Basically each major variant (regular, text, columns,
%D horizontal, etc) needs to be on its own.
diff --git a/tex/context/base/mkiv/supp-box.mkiv b/tex/context/base/mkiv/supp-box.mkiv
index 59e710520..2fce3311a 100644
--- a/tex/context/base/mkiv/supp-box.mkiv
+++ b/tex/context/base/mkiv/supp-box.mkiv
@@ -57,8 +57,8 @@
%D \macros
%D {dontcomplain}
%D
-%D The next macro suppresses over- and underfull messages which
-%D often makes sense when we deal with boxes.
+%D The next macro suppresses over- and underfull messages which often makes sense
+%D when we deal with boxes.
\unexpanded\def\dontcomplain
{\hbadness\plustenthousand
@@ -66,18 +66,15 @@
\hfuzz \maxdimen
\vfuzz \maxdimen}
-%D This module implements some box manipulation macros. Some
-%D are quite simple, some are more advanced and when understood
-%D well, all can be of use.
+%D This module implements some box manipulation macros. Some are quite simple, some
+%D are more advanced and when understood well, all can be of use.
%D
%D \macros
%D {strutdp,strutht,strutwd}
%D
-%D The next shortcuts save memory and keying. The width is
-%D normally zero points (if not, you're in trouble). These
-%D shortcuts can be used like a dimension, opposite to the
-%D core macros \type {\strutdepth} and alike, which are
-%D values.
+%D The next shortcuts save memory and keying. The width is normally zero points (if
+%D not, you're in trouble). These shortcuts can be used like a dimension, opposite
+%D to the core macros \type {\strutdepth} and alike, which are values.
\def\strutdp {\dp\strutbox}
\def\strutht {\ht\strutbox}
@@ -88,8 +85,8 @@
%D \macros
%D {voidbox,nextbox}
%D
-%D Let's start with an easy one. The next macro hides the
-%D ugly \type {@} in \type {\voidb@x}.
+%D Let's start with an easy one. The next macro hides the ugly \type {@} in \type
+%D {\voidb@x}.
\ifdefined\voidbox \else \newbox\voidbox \fi
\ifdefined\nextbox \else \newbox\nextbox \fi
@@ -97,19 +94,17 @@
%D \macros
%D {nextdepth}
%D
-%D Let's start with a rather simple declaration. Sometimes we
-%D need to save the \TEX\ \DIMENSION\ \type{\prevdepth} and
-%D append it later on. The name \type{\nextdepth} suits
-%D this purpose well.
+%D Let's start with a rather simple declaration. Sometimes we need to save the \TEX\
+%D \DIMENSION\ \type{\prevdepth} and append it later on. The name \type {\nextdepth}
+%D suits this purpose well.
\newdimen\nextdepth
%D \macros
%D {smashbox, smashedbox}
%D
-%D Smashing is introduced in \PLAIN\ \TEX, and stands for
-%D reducing the dimensions of a box to zero. The most resolute
-%D one is presented first.
+%D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of
+%D a box to zero. The most resolute one is presented first.
\unexpanded\def\smashbox#1%
{\wd#1\zeropoint
@@ -125,8 +120,8 @@
%D \macros
%D {hsmashbox,vsmashbox}
%D
-%D Smashing can be used for overlaying boxes. Depending on
-%D the mode, horizontal or vertical, one can use:
+%D Smashing can be used for overlaying boxes. Depending on the mode, horizontal or
+%D vertical, one can use:
\unexpanded\def\hsmashbox#1%
{\wd#1\zeropoint}
@@ -135,8 +130,7 @@
{\ht#1\zeropoint
\dp#1\zeropoint}
-%D The next implementation is less sensitive for spurious
-%D spaces.
+%D The next implementation is less sensitive for spurious spaces.
\newcount\c_boxes_register
@@ -174,10 +168,9 @@
%D {hsmash,vsmash,
%D hsmashed,vsmashed}
%D
-%D While the previous macros expected a \BOX, the next act on a
-%D content. They are some subtle differences betreen the smash
-%D and smashed alternatives. The later ones reduce all
-%D dimensions to zero.
+%D While the previous macros expected a \BOX, the next act on a content. They are
+%D some subtle differences betreen the smash and smashed alternatives. The later
+%D ones reduce all dimensions to zero.
\unexpanded\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox}
\unexpanded\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox}
@@ -227,10 +220,9 @@
%D \macros
%D {smash}
%D
-%D This smash alternative takes an optional arg [whdtb] as
-%D well as is potentially catcode safer. It is needed by the
-%D math module (although the \type {\leavevmode} is not added
-%D here).
+%D This smash alternative takes an optional arg [whdtb] as well as is potentially
+%D catcode safer. It is needed by the math module (although the \type {\leavevmode}
+%D is not added here).
\unexpanded\def\smash
{\begingroup
@@ -304,12 +296,12 @@
%D \macros
%D {phantom, hphantom, vphantom, mathstrut}
%D
-%D The next implementation of \type {\phantom} cum suis does
-%D not grab an argument in the non||math case, which is better.
+%D The next implementation of \type {\phantom} cum suis does not grab an argument in
+%D the non||math case, which is better.
%D
-%D Due to a complicated call to \type {\mathpallete} and
-%D thereby \type {\mathchoice}, the next macro looks ugly.
-%D We also take care of non||braced arguments.
+%D Due to a complicated call to \type {\mathpallete} and thereby \type
+%D {\mathchoice}, the next macro looks ugly. We also take care of non||braced
+%D arguments.
\unexpanded\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed }
\unexpanded\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v}
@@ -382,8 +374,7 @@
%D \macros
%D {getboxheight}
%D
-%D Although often needed, \TEX\ does not support arithmics
-%D like:
+%D Although often needed, \TEX\ does not support arithmics like:
%D
%D \starttyping
%D \dimen0 = \ht0 + \dp0
@@ -409,33 +400,29 @@
%D {#1\ht#3\advance#1\dp#3\relax}
%D \stoptyping
%D
-%D The next alternative is slightly more clever, since
-%D it accepts \type {{12}} as well as \type {12} as box
-%D number.
+%D The next alternative is slightly more clever, since it accepts \type {{12}} as
+%D well as \type {12} as box number.
\unexpanded\def\getboxheight#1\of#2\box#3%
{\def\next{#1\dimexpr\ht\c_boxes_register+\dp\c_boxes_register\relax}%
\afterassignment\next\c_boxes_register=#3}
-%D For a long time the following three macros were part of
-%D the grid snapping core module, but it makes more sense to
-%D have them here so that users can see them.
+%D For a long time the following three macros were part of the grid snapping core
+%D module, but it makes more sense to have them here so that users can see them.
%D
%D \macros
%D {getnoflines, getroundednoflines, getrawnoflines}
%D
-%D Het commando \type{\getnoflines} converteert een hoogte
-%D (dimensie) in een aantal regels en kent dit toe aan
-%D \type{\noflines}.
+%D Het commando \type {\getnoflines} converteert een hoogte (dimensie) in een aantal
+%D regels en kent dit toe aan \type {\noflines}.
%D
%D \starttyping
%D \getnoflines{dimensie}
%D \stoptyping
%D
-%D Er wordt gedeeld door \type{\openlineheight} en een hoogte
-%D van~0pt komt overeen met 0~regels. The raw alternative
-%D does not round.
-
+%D Er wordt gedeeld door \type {\openlineheight} en een hoogte van~0pt komt overeen
+%D met 0~regels. The raw alternative does not round.
+%D
%D For a long time we had:
%D
%D \starttyping
@@ -538,9 +525,9 @@
%D \macros
%D {determinenoflines}
%D
-%D The next macro determines the number of lines and
-%D returns it it \type {\noflines}. The macro works
-%D reasonable well as long as the content can be unboxed.
+%D The next macro determines the number of lines and returns it it \type
+%D {\noflines}. The macro works reasonable well as long as the content can be
+%D unboxed.
%D
%D \starttyping
%D \determinenoflines{test\\test}
@@ -569,9 +556,8 @@
%D \macros
%D {doiftextelse, doiftext}
%D
-%D When \type {\doifelse} cum suis hopelessly fail, for
-%D instance because we pass data, we can fall back on the next
-%D macro:
+%D When \type {\doifelse} cum suis hopelessly fail, for instance because we pass
+%D data, we can fall back on the next macro:
%D
%D \starttyping
%D \doiftextelse {data} {then branch} {else branch}
@@ -605,23 +591,19 @@
%D \macros
%D {dowithnextbox,nextbox}
%D
-%D Sometimes we want a macro to grab a box and do something
-%D on the content. One could pass an argument to a box, but
-%D this can violate the specific \CATCODES\ of its content and
-%D leads to unexpected results. The next macro treats the
-%D following braced text as the content of a box and
-%D manipulates it afterwards in a predefined way.
+%D Sometimes we want a macro to grab a box and do something on the content. One
+%D could pass an argument to a box, but this can violate the specific \CATCODES\ of
+%D its content and leads to unexpected results. The next macro treats the following
+%D braced text as the content of a box and manipulates it afterwards in a predefined
+%D way.
%D
-%D The first argument specifies what to do with the content.
-%D This content is available in \type{\nextbox}. The second
-%D argument is one of \type{\hbox}, \type{\vbox} or
-%D \type{\vtop}. The third argument must be grouped with
-%D \type{\bgroup} and \type{\egroup}, \type{{...}} or can be
-%D a \type{\box} specification.
+%D The first argument specifies what to do with the content. This content is
+%D available in \type {\nextbox}. The second argument is one of \type {\hbox}, \type
+%D {\vbox} or \type {\vtop}. The third argument must be grouped with \type {\bgroup}
+%D and \type {\egroup}, \type {{...}} or can be a \type {\box} specification.
%D
-%D In \CONTEXT\ this macro is used for picking up a box and
-%D treating it according to earlier specifications. We use for
-%D instance something like:
+%D In \CONTEXT\ this macro is used for picking up a box and treating it according to
+%D earlier specifications. We use for instance something like:
%D
%D \starttyping
%D \def\getfloat%
@@ -636,9 +618,8 @@
%D {...#1...}
%D \stoptyping
%D
-%D In this implementation the \type{\aftergroup} construction
-%D is needed because \type{\afterassignment} is executed inside
-%D the box.
+%D In this implementation the \type {\aftergroup} construction is needed because
+%D \type {\afterassignment} is executed inside the box.
\unexpanded\def\dowithnextbox#1%
{\def\syst_boxes_with_next_box{#1}%
@@ -684,14 +665,14 @@
%D \setbox\nextbox#2}
%D \stoptyping
%D
-%D This alternative also accepts \type{\box0} and alike, but
-%D we don't really need this functionality now.
+%D This alternative also accepts \type {\box0} and alike, but we don't really need
+%D this functionality now.
%D \macros
%D {nextboxht,nextboxwd,nextboxdp,flushnextbox}
%D
-%D The next couple of shortcuts saves us memory as well as
-%D \type {{}}'s in passing parameters.
+%D The next couple of shortcuts saves us memory as well as \type {{}}'s in passing
+%D parameters.
\def\nextboxht {\ht\nextbox}
\def\nextboxwd {\wd\nextbox}
@@ -703,9 +684,8 @@
%D \macros
%D {dowithnextboxcontent}
%D
-%D But, occasionally we do need to pass some local settings
-%D without wanting to use additional grouping. Therefore we
-%D provide:
+%D But, occasionally we do need to pass some local settings without wanting to use
+%D additional grouping. Therefore we provide:
%D
%D \starttyping
%D \dowithnextboxcontent{inside}{after}{box content}
@@ -731,8 +711,8 @@
%D \macros
%D {llap, rlap, tlap, blap, clap}
%D
-%D Some well known friends, but we implement them our own
-%D way. We want the macros to work in both math and text mode.
+%D Some well known friends, but we implement them our own way. We want the macros to
+%D work in both math and text mode.
\def\dodorlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup}
\def\dodollap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup}
@@ -764,16 +744,14 @@
%D shapebox,
%D ifreshapingbox}
%D
-%D The next utility macro originates from some linenumbering
-%D mechanism. Due to \TEX's advanced way of typesetting
-%D paragraphs, it's not easy to do things on a line||by||line
-%D basis. This macro is able to reprocess a given box and can
-%D act upon its vertical boxed components, such as lines. The
-%D unwinding sequence in this macro is inspired by a \NTG\
-%D workshop of David Salomon in June 1992.
+%D The next utility macro originates from some linenumbering mechanism. Due to
+%D \TEX's advanced way of typesetting paragraphs, it's not easy to do things on a
+%D line||by||line basis. This macro is able to reprocess a given box and can act
+%D upon its vertical boxed components, such as lines. The unwinding sequence in this
+%D macro is inspired by a \NTG\ workshop of David Salomon in June 1992.
%D
-%D First we have to grab the piece of text we want to act
-%D upon. This is done by means of the duo macros:
+%D First we have to grab the piece of text we want to act upon. This is done by
+%D means of the duo macros:
%D
%D \starttyping
%D \beginofshapebox
@@ -781,16 +759,14 @@
%D \endofshapebox
%D \stoptyping
%D
-%D When all texts is collected, we can call \type{\reshapebox}
-%D and do something with it's vertical components. We can make
-%D as much passes as needed. When we're done, the box can be
-%D unloaded with \type{\flushshapebox}. The only condition in
-%D this scheme is that \type{\reshapebox} must somehow unload
-%D the \BOX\ \type{\shapebox}.
+%D When all texts is collected, we can call \type {\reshapebox} and do something
+%D with it's vertical components. We can make as much passes as needed. When we're
+%D done, the box can be unloaded with \type {\flushshapebox}. The only condition in
+%D this scheme is that \type {\reshapebox} must somehow unload the \BOX\ \type
+%D {\shapebox}.
%D
-%D An important aspect is that the content is unrolled
-%D bottom||up. The next example illustrates this maybe
-%D unexpected characteristic.
+%D An important aspect is that the content is unrolled bottom||up. The next example
+%D illustrates this maybe unexpected characteristic.
%D
%D \startbuffer
%D \beginofshapebox
@@ -810,8 +786,7 @@
%D
%D \getbuffer
%D
-%D As we can see, when some kind of numbering is done, we have
-%D to add a second pass.
+%D As we can see, when some kind of numbering is done, we have to add a second pass.
%D
%D \startbuffer
%D \newcounter\LineNumber
@@ -835,9 +810,9 @@
%D
%D \getbuffer
%D
-%D This example shows that the content of the box is still
-%D available after flushing. Another feature is that only the
-%D last reshaping counts. Multiple reshaping can be done by:
+%D This example shows that the content of the box is still available after flushing.
+%D Another feature is that only the last reshaping counts. Multiple reshaping can be
+%D done by:
%D
%D \startbuffer
%D \beginofshapebox
@@ -856,26 +831,23 @@
%D
%D \getbuffer
%D
-%D The macros are surprisingly easy to follow and in fact
-%D introduce no new concepts. Nearly all books on \TEX\ show
-%D similar solutions for unwinding \BOXES.
+%D The macros are surprisingly easy to follow and in fact introduce no new concepts.
+%D Nearly all books on \TEX\ show similar solutions for unwinding \BOXES.
%D
-%D Some macros, like footnote ones, can be sensitive for
-%D reshaping, which can result in an endless loop. We
-%D therefore offer:
+%D Some macros, like footnote ones, can be sensitive for reshaping, which can result
+%D in an endless loop. We therefore offer:
%D
%D \starttyping
%D \ifreshapingbox
%D \stoptyping
%D
-%D Some \CONTEXT\ commands are protected this way. Anyhow,
-%D reshaping is aborted after 100 dead cycles.
+%D Some \CONTEXT\ commands are protected this way. Anyhow, reshaping is aborted
+%D after 100 dead cycles.
%D
-%D By the way, changing the height and depth of \BOX\
-%D \type{\shapebox} results in bad spacing. This means that
-%D for instance linenumbers etc. should be given zero height
-%D and depth before being lapped into the margin. The
-%D previous examples ignore this side effect, but beware!
+%D By the way, changing the height and depth of \BOX\ \type {\shapebox} results in
+%D bad spacing. This means that for instance linenumbers etc. should be given zero
+%D height and depth before being lapped into the margin. The previous examples
+%D ignore this side effect, but beware!
\newif \ifsomeshapeleft
\newif \ifreshapingbox
@@ -1034,9 +1006,8 @@
% \kern-\dp\newshapebox\relax
\fi}
-%D For absolute control, one can use \type{\doreshapebox}
-%D directly. This macro takes four arguments, that take care
-%D of:
+%D For absolute control, one can use \type {\doreshapebox} directly. This macro
+%D takes four arguments, that take care of:
%D
%D \startitemize[n,packed]
%D \item \type{\shapebox}
@@ -1048,10 +1019,9 @@
%D \macros
%D {shapedhbox}
%D
-%D When constructing a new box, using the content of \type
-%D {\shapebox}, one can best use \type {\shapedhbox} instead
-%D of \type {\hbox}, since it manages the height and depth of
-%D the line.
+%D When constructing a new box, using the content of \type {\shapebox}, one can best
+%D use \type {\shapedhbox} instead of \type {\hbox}, since it manages the height and
+%D depth of the line.
\unexpanded\def\shapedhbox % lines with non strutted dimensions have
{\expanded{\dowithnextbox % interlineskip so if we want the original
@@ -1066,8 +1036,8 @@
%D hyphenatedfile,
%D dohyphenateword}
%D
-%D We no longer use the pure \TEX\ variant. In due time we will
-%D report some more advanced statistics.
+%D We no longer use the pure \TEX\ variant. In due time we will report some more
+%D advanced statistics.
%D
%D \starttyping
%D \showhyphens{dohyphenatedword}
@@ -1104,11 +1074,10 @@
%D \macros
%D {processtokens}
%D
-%D We fully agree with (most) typographers that inter||letter
-%D spacing is only permitted in fancy titles, we provide a
-%D macro that can be used to do so. Because this is
-%D (definitely and fortunately) no feature of \TEX, we have to
-%D step through the token list ourselves.
+%D We fully agree with (most) typographers that inter||letter spacing is only
+%D permitted in fancy titles, we provide a macro that can be used to do so. Because
+%D this is (definitely and fortunately) no feature of \TEX, we have to step through
+%D the token list ourselves.
%D
%D \starttyping
%D \processtokens {before} {between} {after} {space} {tokens}
@@ -1126,8 +1095,8 @@
%D
%D \getbuffer
%D
-%D The list of tokens may contain spaces, while \type{\\},
-%D \type{{}} and \type{\ } are handled as space too.
+%D The list of tokens may contain spaces, while \type {\\}, \type {{}} and \type {\
+%D } are handled as space too.
\unexpanded\def\processtokens#1#2#3#4#5%
{\begingroup
@@ -1171,20 +1140,18 @@
%D \macros
%D {doboundtext}
%D
-%D Sometimes there is not enough room to show the complete
-%D (line of) text. In such a situation we can strip of some
-%D characters by using \type{\doboundtext}. When the text is
-%D wider than the given width, it's split and the third
-%D argument is appended. When the text to be checked is packed
-%D in a command, we'll have to use \type{\expandafter}.
+%D Sometimes there is not enough room to show the complete (line of) text. In such a
+%D situation we can strip of some characters by using \type {\doboundtext}. When the
+%D text is wider than the given width, it's split and the third argument is
+%D appended. When the text to be checked is packed in a command, we'll have to use
+%D \type {\expandafter}.
%D
%D \starttyping
%D \doboundtext{a very, probably to long, text}{3cm}{...}
%D \stoptyping
%D
-%D When calculating the room needed, we take the width of the
-%D third argument into account, which leads to a bit more
-%D complex macro than needed at first sight.
+%D When calculating the room needed, we take the width of the third argument into
+%D account, which leads to a bit more complex macro than needed at first sight.
\def\dodoboundtext#1%
{\setbox\scratchboxone\hbox{#1}%
@@ -1205,18 +1172,17 @@
%D \macros
%D {limitatetext}
%D
-%D A bit more beautiful alternative for the previous command is
-%D the next one. This command is more robust because we let
-%D \TEX\ do most of the job. The previous command works better
-%D on text that cannot be hyphenated.
+%D A bit more beautiful alternative for the previous command is the next one. This
+%D command is more robust because we let \TEX\ do most of the job. The previous
+%D command works better on text that cannot be hyphenated.
%D
%D \starttyping
%D \limitatetext {text} {width} {sentinel}
%D \limitatetext {text} {-width} {prelude}
%D \stoptyping
%D
-%D When no width is given, the whole text comes available. The
-%D sentinel is optional. This is about the third version.
+%D When no width is given, the whole text comes available. The sentinel is optional.
+%D This is about the third version.
\ifdefined\fakecompoundhyphen\else \let\fakecompoundhyphen\relax \fi
\ifdefined\veryraggedright \else \def\veryraggedright{\raggedright} \fi
@@ -1477,10 +1443,9 @@
%D \macros
%D {sbox}
%D
-%D This is a rather strange command. It grabs some box content
-%D and and limits the size to the height and depth of a
-%D \type{\strut}. The resulting bottom||alligned box can be used
-%D aside other ones, without disturbing the normal baseline
+%D This is a rather strange command. It grabs some box content and and limits the
+%D size to the height and depth of a \type {\strut}. The resulting bottom||alligned
+%D box can be used aside other ones, without disturbing the normal baseline
%D distance.
%D
%D \startbuffer
@@ -1496,10 +1461,9 @@
%D \getbuffer
%D \stopexample
%D
-%D Before displaying the result we added some skip, otherwise
-%D the first two lines would have ended up in the text. This
-%D macro can be useful when building complicated menus, headers
-%D and footers and|/|or margin material.
+%D Before displaying the result we added some skip, otherwise the first two lines
+%D would have ended up in the text. This macro can be useful when building
+%D complicated menus, headers and footers and|/|or margin material.
\unexpanded\def\sbox
{\vbox\bgroup
@@ -1533,8 +1497,7 @@
%D \macros
%D {struttedbox}
%D
-%D This boxing macro limits the height and depth to those of
-%D a strut.
+%D This boxing macro limits the height and depth to those of a strut.
\unexpanded\def\struttedbox
{\hpack\bgroup
@@ -1549,9 +1512,8 @@
%D \macros
%D {topskippedbox}
%D
-%D This macro compensates the difference between the topskip
-%D and strutheight. Watch how we preserve the depth when it
-%D equals strutdepth.
+%D This macro compensates the difference between the topskip and strutheight. Watch
+%D how we preserve the depth when it equals strutdepth.
\unexpanded\def\topskippedbox
{\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox}
@@ -1565,13 +1527,12 @@
%D \macros
%D {centeredbox, centerednextbox}
%D
-%D Here is another strange one. This one offers a sort of overlay
-%D with positive or negative offsets. This command can be used
-%D in well defined areas where no offset options are available.
-%D We first used it when building a button inside the margin
-%D footer, where the button should have a horizontal offset and
-%D should be centered with respect to the surrounding box. The
-%D last of the three examples we show below says:
+%D Here is another strange one. This one offers a sort of overlay with positive or
+%D negative offsets. This command can be used in well defined areas where no offset
+%D options are available. We first used it when building a button inside the margin
+%D footer, where the button should have a horizontal offset and should be centered
+%D with respect to the surrounding box. The last of the three examples we show below
+%D says:
%D
%D \starttyping
%D \vsize=3cm
@@ -1581,8 +1542,8 @@
%D {\vrule width \hsize height \vsize}}}
%D \stoptyping
%D
-%D Here the \type{\ruledvbox} just shows the surrounding box
-%D and \type{\vrule} is used to show the centered box.
+%D Here the \type {\ruledvbox} just shows the surrounding box and \type {\vrule} is
+%D used to show the centered box.
%D
%D \def\AnExample#1#2%
%D {\vsize=3cm
@@ -1599,14 +1560,12 @@
%D \stopcombination
%D \stoplinecorrection
%D
-%D This command takes two optional arguments: \type{width} and
-%D \type{height}. Observing readers can see that we use \TEX's
-%D own scanner for grabbing these arguments: \type{#1#} reads
-%D everyting till the next brace and passes it to both rules.
-%D The setting of the box dimensions at the end is needed for
-%D special cases. The dimensions of the surrounding box are kept
-%D intact. This commands handles positive and negative
-%D dimensions (which is why we need two boxes with rules).
+%D This command takes two optional arguments: \type {width} and \type {height}.
+%D Observing readers can see that we use \TEX's own scanner for grabbing these
+%D arguments: \type {#1#} reads everyting till the next brace and passes it to both
+%D rules. The setting of the box dimensions at the end is needed for special cases.
+%D The dimensions of the surrounding box are kept intact. This commands handles
+%D positive and negative dimensions (which is why we need two boxes with rules).
\unexpanded\def\centeredbox#1#% height +/-dimen width +/-dimen
{\bgroup
@@ -1666,8 +1625,8 @@
%D \centerbox <optional specs> {content}
%D \stoptyping
%D
-%D When omitted, the current \type {\hsize} and \type
-%D {\vsize} are used. Local dimensions are supported.
+%D When omitted, the current \type {\hsize} and \type {\vsize} are used. Local
+%D dimensions are supported.
\unexpanded\def\centerbox#1#% optional height +/-dimen width +/-dimen
{\bgroup
@@ -1684,27 +1643,21 @@
%D \macros
%D {setrigidcolumnhsize,rigidcolumnbalance,rigidcolumnlines}
%D
-%D These macros are copied from the \TEX book, page~397, and
-%D extended by a macro that sets the \type{\hsize}.
+%D These macros are copied from the \TEX book, page~397, and extended by a macro
+%D that sets the \type {\hsize}.
%D
%D \starttyping
%D \setrigidcolumnhsize {total width} {distance} {n}
%D \rigidcolumnbalance {box}
%D \stoptyping
%D
-%D Both these macros are for instance used in typesetting
-%D footnotes.
-%D
-%D Men kan het proces van breken enigzins beinvloeden met de
-%D volgende twee switches:
+%D Both these macros are for instance used in typesetting footnotes. The following
+%D flags influence the process.
\newif\ifalignrigidcolumns
\newif\ifstretchrigidcolumns
\newif\iftightrigidcolumns % if true: just a vbox, no depth/noflines/gridsnap corrrections
-%D De eerste switch bepaald het uitlijnen, de tweede rekt de
-%D individuele kolommen op naar \type{\vsize}.
-
\unexpanded\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr
{\xdef\savedrigidhsize{\the\hsize}%
\hsize#1\relax
@@ -1791,9 +1744,8 @@
%D \macros
%D {startvboxtohbox,stopvboxtohbox,convertvboxtohbox}
%D
-%D Here is another of Knuth's dirty tricks, as presented on
-%D pages 398 and 399 of the \TEX book. These macros can be used
-%D like:
+%D Here is another of Knuth's dirty tricks, as presented on pages 398 and 399 of the
+%D \TEX book. These macros can be used like:
%D
%D \starttyping
%D \vbox
@@ -1809,14 +1761,14 @@
%D \egroup
%D \stoptyping
%D
-%D These macros are used in reformatting footnotes, so they do
-%D what they're meant for.
+%D These macros are used in reformatting footnotes, so they do what they're meant
+%D for.
\newdimen\vboxtohboxslack
\newdimen\hboxestohboxslack
-% Create line and fake height of paragraph by messign with heights:
-% a nice hack by DEK himself.
+%D Create line and fake height of paragraph by messign with heights: a nice hack by
+%D DEK himself.
%\unexpanded\def\setvboxtohbox
% {\bgroup
@@ -1933,8 +1885,8 @@
%D \macros
%D {unhhbox}
%D
-%D The next macro is used in typesetting inline headings.
-%D Let's first look at the macro and then show an example.
+%D The next macro is used in typesetting inline headings. Let's first look at the
+%D macro and then show an example.
\newbox \unhhedbox
\newbox \hhbox
@@ -1977,10 +1929,9 @@
\afterassignment\dohboxofvbox
\scratchcounter=}
-%D This macro can be used to break a paragraph apart and treat
-%D each line seperately, for instance, making it clickable. The
-%D main complication is that we want to be able to continue the
-%D paragraph, something that's needed in the in line section
+%D This macro can be used to break a paragraph apart and treat each line seperately,
+%D for instance, making it clickable. The main complication is that we want to be
+%D able to continue the paragraph, something that's needed in the in line section
%D headers.
%D
%D \startbuffer
@@ -1999,23 +1950,22 @@
%D
%D \typebuffer
%D
-%D Not that nice a definition, but effective. Note the stretch
-%D we've build in the line that connects the two paragraphs.
+%D Not that nice a definition, but effective. Note the stretch we've build in the
+%D line that connects the two paragraphs.
%D \macros
%D {doifcontent}
%D
-%D When processing depends on the availability of content, one
-%D can give the next macro a try.
+%D When processing depends on the availability of content, one can give the next
+%D macro a try.
%D
%D \starttyping
%D \doifcontent{pre content}{post content}{no content}\somebox
%D \stoptyping
%D
-%D Where \type{\somebox} is either a \type{\hbox} or
-%D \type{\vbox}. If the dimension of this box suggest some
-%D content, the resulting box is unboxed and surrounded by the
-%D first two arguments, else the third arguments is executed.
+%D Where \type {\somebox} is either a \type {\hbox} or \type {\vbox}. If the
+%D dimension of this box suggest some content, the resulting box is unboxed and
+%D surrounded by the first two arguments, else the third arguments is executed.
\unexpanded\def\doifcontent#1#2#3%
{\dowithnextbox
@@ -2049,17 +1999,17 @@
%D
%D \getbuffer
%D
-%D Where the last call of course does not show up in this
-%D document, but definitely generates a confusing message.
+%D Where the last call of course does not show up in this document, but definitely
+%D generates a confusing message.
%D \macros
%D {processboxes}
%D
-%D The next macro gobble boxes and is for instance used for
-%D overlays. First we show the general handler.
+%D The next macro gobble boxes and is for instance used for overlays. First we show
+%D the general handler.
-% we cannot use \futurelet here as we want to skip spaces between
-% boxes (see startoverlay for an example usage)
+% We cannot use \futurelet here as we want to skip spaces between boxes (see
+% startoverlay for an example usage)
% \newbox\processbox % public : this is the one where \nextbox's end up in
%
@@ -2184,8 +2134,7 @@
%D \hbox{\fakebox0}
%D \stoptyping
%D
-%D returns an empty box with the dimensions of the box
-%D specified, here being zero.
+%D returns an empty box with the dimensions of the box specified, here being zero.
\unexpanded\def\fakebox
{\bgroup
@@ -2210,10 +2159,9 @@
%D \rbox{text ...}
%D \stoptyping
%D
-%D Are similar to \type {\vbox}, which means that they also
-%D accept something like \type{to 3cm}, but align to the left,
-%D middle and right. These box types can be used to typeset
-%D paragraphs.
+%D Are similar to \type {\vbox}, which means that they also accept something like
+%D \type {to 3cm}, but align to the left, middle and right. These box types can be
+%D used to typeset paragraphs.
\def\syst_boxes_lrc_process#1{\bgroup\forgetall\let\\\endgraf#1\let\next}
@@ -2225,8 +2173,8 @@
\unexpanded\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter}
\unexpanded\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright }
-%D The alternatives \type {\tbox} and \type {\bbox} can be used
-%D to properly align boxes, like in:
+%D The alternatives \type {\tbox} and \type {\bbox} can be used to properly align
+%D boxes, like in:
%D
%D \setupexternalfigures[directory={../sample}]
%D \startbuffer
@@ -2288,16 +2236,15 @@
%D \macros
%D {boxofsize}
%D
-%D Sometimes we need to construct a box with a height or
-%D width made up of several dimensions. Instead of cumbersome
-%D additions, we can use:
+%D Sometimes we need to construct a box with a height or width made up of several
+%D dimensions. Instead of cumbersome additions, we can use:
%D
%D \starttyping
%D \boxofsize \vbox 10cm 3cm -5cm {the text to be typeset}
%D \stoptyping
%D
-%D This example demonstrates that one can use positive and
-%D negative values. Dimension registers are also accepted.
+%D This example demonstrates that one can use positive and negative values.
+%D Dimension registers are also accepted.
\newdimen\sizeofbox
@@ -2527,8 +2474,8 @@
%D \macros
%D {initializeboxstack,savebox,foundbox}
%D
-%D At the cost of some memory, but saving box registers, we
-%D have implemented a box repository.
+%D At the cost of some memory, but saving box registers, we have implemented a box
+%D repository.
%D
%D \starttyping
%D \initializeboxstack{one}
@@ -2665,9 +2612,8 @@
%D \macros
%D {removedepth, obeydepth}
%D
-%D While \type {\removedepth} removes the preceding depth,
-%D \type {\obeydepth} makes sure we have depth. Both macros
-%D leave the \type {\prevdepth} untouched.
+%D While \type {\removedepth} removes the preceding depth, \type {\obeydepth} makes
+%D sure we have depth. Both macros leave the \type {\prevdepth} untouched.
\unexpanded\def\removedepth
{\ifvmode
@@ -2700,8 +2646,8 @@
%D \macros
%D {makestrutofbox}
%D
-%D This macro sets the dimensions of a box to those of a strut. Sort of obsolete
-%D so it will go away.
+%D This macro sets the dimensions of a box to those of a strut. Sort of obsolete so
+%D it will go away.
\unexpanded\def\makestrutofbox % not used
{\afterassignment\syst_boxes_makestrutofbox\c_boxes_register}
@@ -2714,9 +2660,8 @@
%D \macros
%D {raisebox,lowerbox}
%D
-%D Some more box stuff, related to positioning (under
-%D construction). Nice stuff for a tips and tricks maps
-%D article.
+%D Some more box stuff, related to positioning (under construction). Nice stuff for
+%D a tips and tricks maps article.
%D
%D \starttyping
%D \raisebox{100pt}\hbox{test}
diff --git a/tex/context/base/mkiv/supp-box.mkxl b/tex/context/base/mkiv/supp-box.mkxl
new file mode 100644
index 000000000..920624329
--- /dev/null
+++ b/tex/context/base/mkiv/supp-box.mkxl
@@ -0,0 +1,2930 @@
+%D \module
+%D [ file=supp-box,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=Boxes,
+%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.
+
+\writestatus{loading}{ConTeXt Support Macros / Boxes}
+
+\unprotect
+
+\registerctxluafile{supp-box}{optimize}
+
+% This file is partially cleaned up.
+
+%D First some defaults:
+
+\fixupboxesmode\plusone
+
+% handy to have
+%
+% \hbox to \hsize
+% {\en
+% \switchnaarkorps[5pt]%
+% \emergencystretch2em
+% \dimen0=\baselineskip
+% \baselineskip=\dimen0 plus 1pt
+% \hsize=.2\hsize
+% \vsize=2\hsize
+% \ruledvbox to \vsize{\input tufte \par}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern0pt}\hss
+% \ruledvbox to \vsize{\input tufte \par\vfill}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth\vfill}}
+%
+% \hbox to \hsize
+% {\en
+% \switchnaarkorps[5pt]%
+% \emergencystretch2em
+% \dimen0=\baselineskip
+% \baselineskip=\dimen0 plus 1pt
+% \hsize=.18\hsize
+% \vsize=2.5\hsize
+% \setbox0=\vbox{\input tufte\relax}%
+% \ruledvbox to \vsize{\unvcopy0}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern-\dp0}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern0pt}\hss
+% \ruledvbox to \vsize{\unvcopy0\vfill}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern-\dp0\vfill}}
+
+%D \macros
+%D {dontcomplain}
+%D
+%D The next macro suppresses over- and underfull messages which often makes sense
+%D when we deal with boxes.
+
+\unexpanded\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
+
+%D This module implements some box manipulation macros. Some are quite simple, some
+%D are more advanced and when understood well, all can be of use.
+%D
+%D \macros
+%D {strutdp,strutht,strutwd}
+%D
+%D The next shortcuts save memory and keying. The width is normally zero points (if
+%D not, you're in trouble). These shortcuts can be used like a dimension, opposite
+%D to the core macros \type {\strutdepth} and alike, which are values.
+
+\def\strutdp {\dp\strutbox}
+\def\strutht {\ht\strutbox}
+\def\strutwd {\wd\strutbox}
+\def\struthtdp{\htdp\strutbox}
+\def\strutgap {\dimexpr\ht\strutbox-\dp\strutbox\relax}
+
+%D \macros
+%D {voidbox,nextbox}
+%D
+%D Let's start with an easy one. The next macro hides the ugly \type {@} in \type
+%D {\voidb@x}.
+
+\ifdefined\voidbox \else \newbox\voidbox \fi
+\ifdefined\nextbox \else \newbox\nextbox \fi
+
+%D \macros
+%D {nextdepth}
+%D
+%D Let's start with a rather simple declaration. Sometimes we need to save the \TEX\
+%D \DIMENSION\ \type{\prevdepth} and append it later on. The name \type {\nextdepth}
+%D suits this purpose well.
+
+\newdimen\nextdepth
+
+%D \macros
+%D {smashbox, smashedbox}
+%D
+%D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of
+%D a box to zero. The most resolute one is presented first.
+
+\unexpanded\def\smashbox#1%
+ {\wd#1\zeropoint
+ \ht#1\zeropoint
+ \dp#1\zeropoint}
+
+\unexpanded\def\smashboxed#1%
+ {\wd#1\zeropoint
+ \ht#1\zeropoint
+ \dp#1\zeropoint
+ \box#1\relax}
+
+%D \macros
+%D {hsmashbox,vsmashbox}
+%D
+%D Smashing can be used for overlaying boxes. Depending on the mode, horizontal or
+%D vertical, one can use:
+
+\unexpanded\def\hsmashbox#1%
+ {\wd#1\zeropoint}
+
+\unexpanded\def\vsmashbox#1%
+ {\ht#1\zeropoint
+ \dp#1\zeropoint}
+
+%D The next implementation is less sensitive for spurious spaces.
+
+\newcount\c_boxes_register
+
+\unexpanded\def\smashbox
+ {\afterassignment\syst_boxes_smash_boxes_register\c_boxes_register}
+
+\def\syst_boxes_smash_boxes_register
+ {\wd\c_boxes_register\zeropoint
+ \ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint}
+
+\unexpanded\def\hsmashbox
+ {\afterassignment\syst_boxes_hsmashed_boxes_register\c_boxes_register}
+
+\def\syst_boxes_hsmashed_boxes_register
+ {\wd\c_boxes_register\zeropoint}
+
+\unexpanded\def\vsmashbox
+ {\afterassignment\syst_boxes_vsmashed_boxes_register\c_boxes_register}
+
+\def\syst_boxes_vsmashed_boxes_register
+ {\ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint}
+
+\unexpanded\def\smashedbox
+ {\afterassignment\syst_boxes_smashed_boxes_register\c_boxes_register}
+
+\unexpanded\def\syst_boxes_smashed_boxes_register
+ {\wd\c_boxes_register\zeropoint
+ \ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint
+ \box\c_boxes_register}
+
+%D \macros
+%D {hsmash,vsmash,
+%D hsmashed,vsmashed}
+%D
+%D While the previous macros expected a \BOX, the next act on a content. They are
+%D some subtle differences betreen the smash and smashed alternatives. The later
+%D ones reduce all dimensions to zero.
+
+\unexpanded\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox}
+\unexpanded\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox}
+\unexpanded\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox}
+\unexpanded\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox}
+
+\unexpanded\def\syst_boxes_hsmashed_nextbox
+ {\wd\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+\unexpanded\def\syst_boxes_vsmashed_nextbox
+ {\ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+\unexpanded\def\syst_boxes_smashed_nextbox
+ {\ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \wd\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {smashedhbox,smashedvbox}
+%D
+%D Also handy (all dimensions zeroed):
+%D
+%D \starttyping
+%D \smashedhbox to ... {...}
+%D \smashedvbox to ... {...}
+%D \stoptyping
+
+\unexpanded\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox}
+\unexpanded\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox}
+
+%D First we define a helper. We use a \LUATEX\ feature in order to avoid
+%D mathpalettes.
+
+\newcount\c_boxes_math_style
+
+\unexpanded\def\syst_boxes_math_set_nextbox#1%
+ {\c_boxes_math_style\mathstyle
+ \setbox\nextbox\hbox{\normalstartimath\mathsurround\zeropoint\triggermathstyle\c_boxes_math_style{#1}\normalstopimath}}
+
+%D \macros
+%D {smash}
+%D
+%D This smash alternative takes an optional arg [whdtb] as well as is potentially
+%D catcode safer. It is needed by the math module (although the \type {\leavevmode}
+%D is not added here).
+
+\unexpanded\def\smash
+ {\begingroup
+ \futurelet\nexttoken\syst_boxes_smash}
+
+\def\syst_boxes_smash
+ {\ifx\nexttoken[%
+ \expandafter\syst_boxes_smash_yes
+ \else
+ \expandafter\syst_boxes_smash_nop
+ \fi}
+
+\def\syst_boxes_smash_nop
+ {\edef\m_boxes_smash_options{hd}%
+ \futurelet\nexttoken\syst_boxes_smash_indeed}
+
+\def\syst_boxes_smash_yes[#1]%
+ {\edef\m_boxes_smash_options{#1}%
+ \futurelet\nexttoken\syst_boxes_smash_indeed}
+
+\def\syst_boxes_smash_indeed
+ {\ifmmode
+ \expandafter\syst_boxes_smash_math
+ \orelse\ifx\nexttoken\bgroup
+ \expandafter\syst_boxes_smash_hbox
+ \else
+ \expandafter\syst_boxes_smash_text
+ \fi}
+
+\def\syst_boxes_smash_math#1%
+ {\syst_boxes_math_set_nextbox{#1}%
+ \syst_boxes_smash_process}
+
+\def\syst_boxes_smash_hbox
+ {\dowithnextboxcs\syst_boxes_smash_process\hbox}
+
+\def\syst_boxes_smash_text#1%
+ {\setbox\nextbox\hbox{#1}%
+ \syst_boxes_smash_process}
+
+\def\syst_boxes_smash_process
+ {\expandafter\syst_boxes_smash_process_option\m_boxes_smash_options\relax
+ \box\nextbox
+ \endgroup}
+
+\installcorenamespace {smashoptions}
+
+\setvalue{\??smashoptions w}{\wd\nextbox\zeropoint}
+\setvalue{\??smashoptions h}{\ht\nextbox\zeropoint}
+\setvalue{\??smashoptions d}{\dp\nextbox\zeropoint}
+\setvalue{\??smashoptions t}{\ht\nextbox\zeropoint}
+\setvalue{\??smashoptions b}{\dp\nextbox\zeropoint}
+
+\def\syst_boxes_smash_process_option#1%
+ {\ifx#1\relax\else
+ \begincsname\??smashoptions#1\endcsname
+ \expandafter\syst_boxes_smash_process_option
+ \fi}
+
+\def\syst_boxes_lower_nextbox_dp
+ {\setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}}
+
+%D \starttabulate[|l|l|]
+%D \NC w \NC \ruledhbox{\smash [w]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC h \NC \ruledhbox{\smash [h]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC d \NC \ruledhbox{\smash [d]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC tb \NC \ruledhbox{\smash [tb]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC whd \NC \ruledhbox{\smash[whd]{This is some great smashing, isn't it?}} \NC \NR
+%D \stoptabulate
+
+%D \macros
+%D {phantom, hphantom, vphantom, mathstrut}
+%D
+%D The next implementation of \type {\phantom} cum suis does not grab an argument in
+%D the non||math case, which is better.
+%D
+%D Due to a complicated call to \type {\mathpallete} and thereby \type
+%D {\mathchoice}, the next macro looks ugly. We also take care of non||braced
+%D arguments.
+
+\unexpanded\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed }
+\unexpanded\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v}
+\unexpanded\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h}
+
+\def\syst_boxes_phantom_math #1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make }
+\def\syst_boxes_phantom_math_v#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_v}
+\def\syst_boxes_phantom_math_h#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_h}
+
+\def\syst_boxes_phantom_hbox {\dowithnextboxcs\syst_boxes_phantom_make \hbox} % always hbox
+\def\syst_boxes_phantom_hbox_v{\dowithnextboxcs\syst_boxes_phantom_make_v\hbox} % always hbox
+\def\syst_boxes_phantom_hbox_h{\dowithnextboxcs\syst_boxes_phantom_make_h\hbox} % always hbox
+
+\def\syst_boxes_phantom_text #1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make } % always hbox
+\def\syst_boxes_phantom_text_v#1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make_v} % always hbox
+\def\syst_boxes_phantom_text_h#1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make_h} % always hbox
+
+\def\syst_boxes_phantom_indeed
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math
+ \orelse\ifx\nexttoken\bgroup
+ \expandafter\syst_boxes_phantom_hbox
+ \else
+ \expandafter\syst_boxes_phantom_text
+ \fi}
+
+\def\syst_boxes_phantom_indeed_v
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math_v
+ \orelse\ifx\nexttoken\bgroup
+ \expandafter\syst_boxes_phantom_hbox_v
+ \else
+ \expandafter\syst_boxes_phantom_text_v
+ \fi}
+
+\def\syst_boxes_phantom_indeed_h
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math_h
+ \orelse\ifx\nexttoken\bgroup
+ \expandafter\syst_boxes_phantom_hbox_h
+ \else
+ \expandafter\syst_boxes_phantom_text_h
+ \fi}
+
+\def\syst_boxes_phantom_make
+ {\setbox\scratchbox\emptyhbox
+ \ht\scratchbox\ht\nextbox
+ \dp\scratchbox\dp\nextbox
+ \wd\scratchbox\wd\nextbox
+ \box\scratchbox
+ \endgroup}
+
+\def\syst_boxes_phantom_make_v
+ {\setbox\scratchbox\emptyhbox
+ \ht\scratchbox\ht\nextbox
+ \dp\scratchbox\dp\nextbox
+ \box\scratchbox
+ \endgroup}
+
+\def\syst_boxes_phantom_make_h
+ {\setbox\scratchbox\emptyhbox
+ \wd\scratchbox\wd\nextbox
+ \box\scratchbox
+ \endgroup}
+
+%D We also define plain's \type {\mathstrut}.
+
+\unexpanded\def\mathstrut{\vphantom(} % can be made faster by inlining
+
+%D \macros
+%D {getboxheight}
+%D
+%D Although often needed, \TEX\ does not support arithmics like:
+%D
+%D \starttyping
+%D \dimen0 = \ht0 + \dp0
+%D \stoptyping
+%D
+%D so we implemented:
+%D
+%D \starttyping
+%D \getboxheight ... \of \box...
+%D \stoptyping
+%D
+%D For instance,
+%D
+%D \starttyping
+%D \getboxheight \dimen0 \of \box0
+%D \getboxheight \someheight \of \box \tempbox
+%D \stoptyping
+%D
+%D The implementation is rather stupid:
+%D
+%D \starttyping
+%D \def\getboxheight#1\of#2\box#3%
+%D {#1\ht#3\advance#1\dp#3\relax}
+%D \stoptyping
+%D
+%D The next alternative is slightly more clever, since it accepts \type {{12}} as
+%D well as \type {12} as box number.
+
+\unexpanded\def\getboxheight#1\of#2\box#3%
+ {\def\next{#1\dimexpr\ht\c_boxes_register+\dp\c_boxes_register\relax}%
+ \afterassignment\next\c_boxes_register=#3}
+
+%D For a long time the following three macros were part of the grid snapping core
+%D module, but it makes more sense to have them here so that users can see them.
+%D
+%D \macros
+%D {getnoflines, getroundednoflines, getrawnoflines}
+%D
+%D Het commando \type {\getnoflines} converteert een hoogte (dimensie) in een aantal
+%D regels en kent dit toe aan \type {\noflines}.
+%D
+%D \starttyping
+%D \getnoflines{dimensie}
+%D \stoptyping
+%D
+%D Er wordt gedeeld door \type {\openlineheight} en een hoogte van~0pt komt overeen
+%D met 0~regels. The raw alternative does not round.
+%D
+%D For a long time we had:
+%D
+%D \starttyping
+%D \newcount\noflines
+%D \newdimen\noflinesheight
+%D
+%D \def\dogetnoflines#1#2%
+%D {\noflinesheight#2\relax
+%D \ifzeropt\noflinesheight % \ifdim\noflinesheight=\zeropoint
+%D \noflines\zerocount
+%D \else
+%D \divide\noflinesheight \openlineheight
+%D \noflines\noflinesheight
+%D #1\ifdim\noflines\openlineheight=#2\relax \else
+%D \advance\noflines\ifdim#2>\zeropoint\plusone\else\minusone\fi
+%D \fi\fi
+%D \fi}
+%D
+%D \def\getnoflines {\dogetnoflines\iftrue } % compensated
+%D \def\getrawnoflines{\dogetnoflines\iffalse} % no compensation
+%D \stoptyping
+%D
+%D A more recent variant is:
+
+\ifx\roundingeps\undefined \newdimen\roundingeps \roundingeps=10sp \fi
+
+\newcount\noflines
+\newdimen\noflinesheight
+
+\unexpanded\def\getnoflines#1%
+ {\noflinesheight#1\relax
+ \ifzeropt\noflinesheight
+ \noflines\zerocount
+ \orelse\ifdim\noflinesheight>\zeropoint
+ \advance\noflinesheight-\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \advance\noflines\plusone
+ \else
+ \advance\noflinesheight\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \advance\noflines\minusone
+ \fi}
+
+\unexpanded\def\getroundednoflines#1%
+ {\noflinesheight#1\relax
+ \ifzeropt\noflinesheight
+ \noflines\zerocount
+ \orelse\ifdim\noflinesheight>\zeropoint
+ \advance\noflinesheight\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \else
+ \advance\noflinesheight-\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \fi}
+
+\unexpanded\def\getrawnoflines#1%
+ {\noflinesheight#1\relax
+ \ifzeropt\noflinesheight
+ \noflines\zerocount
+ \orelse\ifdim\noflinesheight>\zeropoint
+ \advance\noflinesheight\roundingeps
+ \advance\noflinesheight.5\openlineheight
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \else
+ \advance\noflinesheight-\roundingeps
+ \advance\noflinesheight-.5\openlineheight
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \fi}
+
+%D Let's proof that it works:
+%D
+%D \startbuffer
+%D \scratchdimen\dimexpr(3pt) \getnoflines\scratchdimen 1=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight) \getnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.1\lineheight) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.5\lineheight) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.9\lineheight) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3pt) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3sp) \getnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight-3sp) \getnoflines\scratchdimen 10=\the\noflines \endgraf
+%D
+%D \scratchdimen\dimexpr(3pt) \getrawnoflines\scratchdimen 0=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.1\lineheight) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.5\lineheight) \getrawnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.9\lineheight) \getrawnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3pt) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3sp) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight-3sp) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {determinenoflines}
+%D
+%D The next macro determines the number of lines and returns it it \type
+%D {\noflines}. The macro works reasonable well as long as the content can be
+%D unboxed.
+%D
+%D \starttyping
+%D \determinenoflines{test\\test}
+%D \determinenoflines{\bfd test\\test}
+%D \determinenoflines{\definedfont[Sans at 40pt]test\\test}
+%D \stoptyping
+
+\def\dodeterminenoflines % can be mkiv'd
+ {\beginofshapebox
+ \unvbox\nextbox
+ \endofshapebox
+ % \global\count1\zerocount
+ % \reshapebox{\global\advance\count1\plusone}%
+ % \egroup\noflines\count1 }%
+ \scratchcounter\zerocount
+ \reshapebox{\global\advance\scratchcounter\plusone}%
+ \expandafter\egroup\expandafter\noflines\the\scratchcounter\relax}
+
+\unexpanded\def\determinenoflines
+ {\bgroup
+ \forgetall
+ \let\crlf\endgraf
+ \let\\\endgraf
+ \dowithnextboxcs\dodeterminenoflines\vbox}
+
+%D \macros
+%D {doiftextelse, doiftext}
+%D
+%D When \type {\doifelse} cum suis hopelessly fail, for instance because we pass
+%D data, we can fall back on the next macro:
+%D
+%D \starttyping
+%D \doiftextelse {data} {then branch} {else branch}
+%D \doiftext {data} {then branch}
+%D \stoptyping
+
+\unexpanded\def\doifelsetext#1%
+ {\begingroup
+ \setbox\scratchbox\hpack
+ {\settrialtypesetting
+ \ignorespaces#1\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox
+ \endgroup\expandafter\secondoftwoarguments
+ \else
+ \endgroup\expandafter\firstoftwoarguments
+ \fi}
+
+\let\doiftextelse\doifelsetext
+
+\unexpanded\def\doiftext#1%
+ {\begingroup
+ \setbox\scratchbox\hpack
+ {\settrialtypesetting
+ \ignorespaces#1\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox
+ \endgroup\expandafter\gobbleoneargument
+ \else
+ \endgroup\expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {dowithnextbox,nextbox}
+%D
+%D Sometimes we want a macro to grab a box and do something on the content. One
+%D could pass an argument to a box, but this can violate the specific \CATCODES\ of
+%D its content and leads to unexpected results. The next macro treats the following
+%D braced text as the content of a box and manipulates it afterwards in a predefined
+%D way.
+%D
+%D The first argument specifies what to do with the content. This content is
+%D available in \type {\nextbox}. The second argument is one of \type {\hbox}, \type
+%D {\vbox} or \type {\vtop}. The third argument must be grouped with \type {\bgroup}
+%D and \type {\egroup}, \type {{...}} or can be a \type {\box} specification.
+%D
+%D In \CONTEXT\ this macro is used for picking up a box and treating it according to
+%D earlier specifications. We use for instance something like:
+%D
+%D \starttyping
+%D \def\getfloat%
+%D {\def\handlefloat{...\box\nextbox...}
+%D \dowithnextboxcs\handlefloat\vbox}
+%D \stoptyping
+%D
+%D instead of:
+%D
+%D \starttyping
+%D \def\getfloat#1%
+%D {...#1...}
+%D \stoptyping
+%D
+%D In this implementation the \type {\aftergroup} construction is needed because
+%D \type {\afterassignment} is executed inside the box.
+
+\unexpanded\def\dowithnextbox#1%
+ {\def\syst_boxes_with_next_box{#1}%
+ \afterassignment\syst_boxes_with_next_box_indeed
+ \setbox\nextbox}
+
+\def\syst_boxes_with_next_box_indeed
+ {\aftergroup\syst_boxes_with_next_box}
+
+\unexpanded\def\dowithnextboxcs#1%
+ {\let\syst_boxes_with_next_box#1%
+ \afterassignment\syst_boxes_with_next_box_indeed
+ \setbox\nextbox}
+
+%D So in fact we get:
+%D
+%D \starttyping
+%D \setbox\nextbox { \aftergroup\syst_boxes_with_next_box ... }
+%D \stoptyping
+%D
+%D or
+%D
+%D \starttyping
+%D \setbox\nextbox { ... } \syst_boxes_with_next_box
+%D \stoptyping
+%D
+%D A slower but more versatile implementation is:
+%D
+%D \starttyping
+%D \unexpanded\def\dowithnextbox#1#2%
+%D {\def\syst_boxes_with_next_box{#1}%
+%D \ifx#2\hbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else\ifx#2\vbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else\ifx#2\vtop
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else\ifx#2\normalvcenter
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else
+%D \afterassignment\syst_boxes_with_next_box
+%D \fi\fi\fi\fi
+%D \setbox\nextbox#2}
+%D \stoptyping
+%D
+%D This alternative also accepts \type {\box0} and alike, but we don't really need
+%D this functionality now.
+
+%D \macros
+%D {nextboxht,nextboxwd,nextboxdp,flushnextbox}
+%D
+%D The next couple of shortcuts saves us memory as well as \type {{}}'s in passing
+%D parameters.
+
+\def\nextboxht {\ht\nextbox}
+\def\nextboxwd {\wd\nextbox}
+\def\nextboxdp {\dp\nextbox}
+\def\nextboxhtdp {\htdp\nextbox}
+
+\unexpanded\def\flushnextbox{\box\nextbox}
+
+%D \macros
+%D {dowithnextboxcontent}
+%D
+%D But, occasionally we do need to pass some local settings without wanting to use
+%D additional grouping. Therefore we provide:
+%D
+%D \starttyping
+%D \dowithnextboxcontent{inside}{after}{box content}
+%D \stoptyping
+%D
+%D {\em todo: Search source for potential usage!}
+
+\unexpanded\def\dowithnextboxcontent#1#2% inside, after
+ {\def\syst_boxes_with_next_box_one{#2}%
+ \def\syst_boxes_with_next_box_two{#1}%
+ \afterassignment\syst_boxes_with_next_box_content_indeed
+ \setbox\nextbox}
+
+\unexpanded\def\dowithnextboxcontentcs#1#2% inside, after
+ {\let\syst_boxes_with_next_box_one#2%
+ \let\syst_boxes_with_next_box_two#1%
+ \afterassignment\syst_boxes_with_next_box_content_indeed
+ \setbox\nextbox}
+
+\def\syst_boxes_with_next_box_content_indeed
+ {\syst_boxes_with_next_box_two\aftergroup\syst_boxes_with_next_box_one}
+
+%D \macros
+%D {llap, rlap, tlap, blap, clap}
+%D
+%D Some well known friends, but we implement them our own way. We want the macros to
+%D work in both math and text mode.
+
+\def\dodorlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup}
+\def\dodollap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup}
+\def\dodoclap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup}
+
+\def\dorlap{\begingroup\dowithnextboxcs\dodorlap\hbox}
+\def\dollap{\begingroup\dowithnextboxcs\dodollap\hbox}
+\def\doclap{\begingroup\dowithnextboxcs\dodoclap\hbox}
+
+\def\domathclap{\mathpalette\dodomathclap} \def\dodomathclap#1#2{\doclap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+\def\domathllap{\mathpalette\dodomathllap} \def\dodomathllap#1#2{\dollap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+\def\domathrlap{\mathpalette\dodomathrlap} \def\dodomathrlap#1#2{\dorlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+
+\unexpanded\def\rlap{\mathortext\domathrlap\dorlap}
+\unexpanded\def\llap{\mathortext\domathllap\dollap}
+\unexpanded\def\clap{\mathortext\domathclap\doclap}
+
+\def\dodotlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup}
+\def\dodoblap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup}
+
+\unexpanded\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox}
+\unexpanded\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox}
+
+%D \macros
+%D {beginofshapebox,
+%D reshapebox, doreshapebox,
+%D flushshapebox,
+%D innerflushshapebox,
+%D shapebox,
+%D ifreshapingbox}
+%D
+%D The next utility macro originates from some linenumbering mechanism. Due to
+%D \TEX's advanced way of typesetting paragraphs, it's not easy to do things on a
+%D line||by||line basis. This macro is able to reprocess a given box and can act
+%D upon its vertical boxed components, such as lines. The unwinding sequence in this
+%D macro is inspired by a \NTG\ workshop of David Salomon in June 1992.
+%D
+%D First we have to grab the piece of text we want to act upon. This is done by
+%D means of the duo macros:
+%D
+%D \starttyping
+%D \beginofshapebox
+%D a piece of text
+%D \endofshapebox
+%D \stoptyping
+%D
+%D When all texts is collected, we can call \type {\reshapebox} and do something
+%D with it's vertical components. We can make as much passes as needed. When we're
+%D done, the box can be unloaded with \type {\flushshapebox}. The only condition in
+%D this scheme is that \type {\reshapebox} must somehow unload the \BOX\ \type
+%D {\shapebox}.
+%D
+%D An important aspect is that the content is unrolled bottom||up. The next example
+%D illustrates this maybe unexpected characteristic.
+%D
+%D \startbuffer
+%D \beginofshapebox
+%D \em \input tufte
+%D \endofshapebox
+%D
+%D \newcounter\LineNumber
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox{\llap{\LineNumber\hskip2em}\box\shapebox}}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D As we can see, when some kind of numbering is done, we have to add a second pass.
+%D
+%D \startbuffer
+%D \newcounter\LineNumber
+%D \newcounter\NumberOfLines
+%D
+%D \reshapebox
+%D {\doglobal\increment\NumberOfLines
+%D \box\shapebox}
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox
+%D {\llap{\LineNumber\ (\NumberOfLines)\hskip2em}%
+%D \box\shapebox}%
+%D \doglobal\decrement\NumberOfLines}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D This example shows that the content of the box is still available after flushing.
+%D Another feature is that only the last reshaping counts. Multiple reshaping can be
+%D done by:
+%D
+%D \startbuffer
+%D \beginofshapebox
+%D \flushshapebox
+%D \endofshapebox
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox{\llap{$\star$\hskip1em}\box\shapebox}%
+%D \doglobal\decrement\NumberOfLines}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D The macros are surprisingly easy to follow and in fact introduce no new concepts.
+%D Nearly all books on \TEX\ show similar solutions for unwinding \BOXES.
+%D
+%D Some macros, like footnote ones, can be sensitive for reshaping, which can result
+%D in an endless loop. We therefore offer:
+%D
+%D \starttyping
+%D \ifreshapingbox
+%D \stoptyping
+%D
+%D Some \CONTEXT\ commands are protected this way. Anyhow, reshaping is aborted
+%D after 100 dead cycles.
+%D
+%D By the way, changing the height and depth of \BOX\ \type {\shapebox} results in
+%D bad spacing. This means that for instance linenumbers etc. should be given zero
+%D height and depth before being lapped into the margin. The previous examples
+%D ignore this side effect, but beware!
+
+\newif \ifsomeshapeleft
+\newif \ifreshapingbox
+
+\newbox \shapebox
+\newcount \shapepenalty
+\newdimen \shapekern
+\newskip \shapeskip
+
+\newbox \newshapebox
+\newbox \oldshapebox
+
+\newcount \shapecounter
+
+\newevery \everyshapebox \relax
+
+\def\shapesignal{.12345678pt} % or 12345sp
+
+\unexpanded\def\reshapebox#1%
+ {\doreshapebox
+ {#1}%
+ {\penalty\shapepenalty}%
+ {\kern \shapekern }%
+ {\vskip \shapeskip }}
+
+\newbox\tmpshapebox
+
+\newif\ifreshapingfailed % may save redundant runs
+
+\def\doreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
+ {\global\reshapingfailedfalse
+ \ifzeropt\ht\oldshapebox % \ifdim\ht\oldshapebox=\zeropoint
+ \setbox\newshapebox\emptyvbox
+ \else
+ \setbox\newshapebox\vbox % can be \vpack
+ {\unvcopy\oldshapebox
+ \setbox\newshapebox\emptybox
+ \shapecounter\zerocount
+ \doloop{\dodoreshapebox{#1}{#2}{#3}{#4}}}%
+ \setbox\newshapebox\box\tmpshapebox
+ \fi}
+
+\ifx\originalshapebox\undefined \let\originalshapebox\oldshapebox \fi
+
+% We will turn this into a \MKIV\ variant (we can use \type {\vpack} too).
+
+\unexpanded\def\insertshapesignal
+ {\hpack to \shapesignal{\strut\hss}% plus \strut
+ \prevdepth\strutdp} % never \nointerlineskip
+
+\unexpanded\def\restoreshapebox % compensates for the signal
+ {\global\setbox\tmpshapebox\vbox{\vskip-\lineheight\unvcopy\oldshapebox}}
+
+\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
+ {\ifnum\lastnodetype=\gluenodecode
+ \shapeskip\lastskip
+ \global\setbox\tmpshapebox\vbox{#4\unvbox\tmpshapebox}%
+ \unskip
+ \orelse\ifnum\lastnodetype=\kernnodecode
+ \shapekern\lastkern
+ \global\setbox\tmpshapebox\vbox{#3\unvbox\tmpshapebox}%
+ \unkern
+ \orelse\ifnum\lastnodetype=\penaltynodecode
+ \shapepenalty\lastpenalty
+ \global\setbox\tmpshapebox\vbox{#2\unvbox\tmpshapebox}%
+ \unpenalty
+ \orelse\ifnum\lastnodetype<\zeropoint
+ \exitloop
+ \else
+ \setbox\shapebox\lastbox
+ \ifvoid\shapebox
+ \orelse\ifdim\wd\shapebox=\shapesignal\relax
+ \exitloop
+ \else
+ \shapecounter\zerocount
+ \global\setbox\tmpshapebox\vbox{#1\unvbox\tmpshapebox}%
+ \fi
+ \fi
+ \ifnum\shapecounter>100 % can be less
+ \global\reshapingfailedtrue
+ \message{!!forced exit from shapebox \the\lastnodetype !!}%
+ \restoreshapebox
+ \exitloop
+ \else
+ \advance\shapecounter \plusone
+ \fi}
+
+\unexpanded\def\beginofshapebox
+ {\setbox\oldshapebox\vbox
+ \bgroup
+ \reshapingboxtrue
+ \the\everyshapebox
+ \insertshapesignal}
+
+\unexpanded\def\endofshapebox
+ {\endgraf
+ \egroup}
+
+\let\beginshapebox\beginofshapebox
+\let\endshapebox \endofshapebox
+
+\unexpanded\def\flushshapebox
+ {\bgroup
+ \ifzeropt\ht\newshapebox % \ifdim\ht\newshapebox=\zeropoint
+ \else
+ % make \prevdepth legal
+ % \par before the next \vskip gives far worse results
+ \ifdim\parskip>\zeropoint\vskip\parskip\else\par\fi
+ % and take a look
+ \ifdim\prevdepth=-\thousandpoint
+ \prevdepth\zeropoint
+ \fi
+ \ifdim\prevdepth<\zeropoint\relax
+ % something like a line or a signal or ...
+ \donetrue
+ \orelse\ifinner
+ % not watertight and not ok
+ \donefalse
+ \orelse\ifdim\pagegoal=\maxdimen
+ \donetrue
+ \else
+ % give the previous line a normal depth
+ \donetrue
+ {\forgeteverypar\verticalstrut}\nobreak
+ \kern-\struttotal % geen \vskip
+ \kern-\parskip
+ % \vskip-\strutdp
+ \fi
+ \scratchdimen\dp\newshapebox
+ \unvbox\newshapebox
+ % \prevdepth=0pt and \dp\newshapebox depend on last line
+ \kern-\scratchdimen % ??
+ % now \prevdepth=0pt
+ \ifdone
+ \kern\strutdp
+ \prevdepth\strutdp
+ \fi
+ \fi
+ \egroup}
+
+%D In real inner situations we can use:
+%D
+%D \starttyping
+%D \flushinnershapebox
+%D \stoptyping
+%D
+%D This one is used in \type{\framed}.
+
+% The kern fails on for instance:
+%
+% \omlijnd[offset=0pt,hoogte=8mm,uitlijnen={rechts,laho}]{\bfa test}
+
+\unexpanded\def\innerflushshapebox
+ {\ifzeropt\ht\newshapebox \else
+ \unvcopy\newshapebox\relax % unvcopy ! else spacing problem
+ % \kern-\dp\newshapebox\relax
+ \fi}
+
+%D For absolute control, one can use \type {\doreshapebox} directly. This macro
+%D takes four arguments, that take care of:
+%D
+%D \startitemize[n,packed]
+%D \item \type{\shapebox}
+%D \item \type{\shapepenalty}
+%D \item \type{\shapekern}
+%D \item \type{\shapeskip}
+%D \stopitemize
+
+%D \macros
+%D {shapedhbox}
+%D
+%D When constructing a new box, using the content of \type {\shapebox}, one can best
+%D use \type {\shapedhbox} instead of \type {\hbox}, since it manages the height and
+%D depth of the line.
+
+\unexpanded\def\shapedhbox % lines with non strutted dimensions have
+ {\expanded{\dowithnextbox % interlineskip so if we want the original
+ {\dp\nextbox\the\ht\shapebox % spacing, we need to preserve the original
+ \dp\nextbox\the\dp\shapebox % height and depth which is definitely
+ \box\nextbox}} % needed if we apply struts to the 'new'
+ \hbox} % box or do something that changed ist size
+
+%D \macros
+%D {hyphenatedword,
+%D hyphenatedpar,
+%D hyphenatedfile,
+%D dohyphenateword}
+%D
+%D We no longer use the pure \TEX\ variant. In due time we will report some more
+%D advanced statistics.
+%D
+%D \starttyping
+%D \showhyphens{dohyphenatedword}
+%D \stoptyping
+
+\unexpanded\def\doshowhyphenatednextbox
+ {\clf_showhyphenatedinlist\nextbox}
+
+\unexpanded\def\showhyphens % hpack: so no processing (we hyphenate in lua)
+ {\dowithnextboxcs\doshowhyphenatednextbox\hpack}
+
+%D The following macros are seldom used but handy for tracing.
+%D
+%D \starttyping
+%D \hyphenatedword{dohyphenatedword}
+%D \hyphenatedpar {\dorecurse{10}{dohyphenatedword }}
+%D \hyphenatedfile{tufte}
+%D \stoptyping
+
+\unexpanded\def\dohyphenatednextbox
+ {\clf_hyphenatedlist\nextbox false\relax
+ \unhbox\nextbox}
+
+\unexpanded\def\hyphenatedword {\dowithnextboxcs\dohyphenatednextbox\hbox}
+\unexpanded\def\hyphenatedpar {\dowithnextboxcs\dohyphenatednextbox\hbox}
+\unexpanded\def\hyphenatedfile#1{\dowithnextboxcs\dohyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}}
+
+\unexpanded\def\dohyphenatednextboxcolor
+ {\clf_hyphenatedlist\nextbox true\relax
+ \unhbox\nextbox}
+
+\unexpanded\def\hyphenatedcoloredword{\dowithnextboxcs\dohyphenatednextboxcolor\hbox}
+
+%D \macros
+%D {processtokens}
+%D
+%D We fully agree with (most) typographers that inter||letter spacing is only
+%D permitted in fancy titles, we provide a macro that can be used to do so. Because
+%D this is (definitely and fortunately) no feature of \TEX, we have to step through
+%D the token list ourselves.
+%D
+%D \starttyping
+%D \processtokens {before} {between} {after} {space} {tokens}
+%D \stoptyping
+%D
+%D An example of a call is:
+%D
+%D \startbuffer
+%D \processtokens {[} {+} {]} {\space} {hello world}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This results in:
+%D
+%D \getbuffer
+%D
+%D The list of tokens may contain spaces, while \type {\\}, \type {{}} and \type {\
+%D } are handled as space too.
+
+\unexpanded\def\processtokens#1#2#3#4#5%
+ {\begingroup
+ \def\lastcharacter{\lastcharacter}%
+ \def\space{ }%
+ \let\\=\space
+ \def\before {#1}%
+ \def\between{#2}%
+ \def\after {#3}%
+ \def\white {#4}%
+ \let\savedbefore\before
+ \doprocesstokens#5\lastcharacter
+ \endgroup}
+
+\def\doprocesstokens% the space after = is essential
+ {\afterassignment\dodoprocesstokens\let\nextprocessedtoken= }
+
+\def\dodoprocesstokens
+ {\ifx\nextprocessedtoken\lastcharacter
+ \after
+ \let\nextprocessedtoken\relax
+ \orelse\ifx\nextprocessedtoken\bgroup
+ \def\nextprocessedtoken
+ {\dowithnextbox
+ {\before{\copy\nextbox}% \before can use nextbox several times
+ \let\before\between
+ \doprocesstokens}
+ \hbox\bgroup}%
+ \else
+ \expandafter\if\space\nextprocessedtoken
+ \after\white
+ \let\before\savedbefore
+ \else
+ \before\nextprocessedtoken
+ \let\before\between
+ \fi
+ \let\nextprocessedtoken\doprocesstokens
+ \fi
+ \nextprocessedtoken}
+
+%D \macros
+%D {doboundtext}
+%D
+%D Sometimes there is not enough room to show the complete (line of) text. In such a
+%D situation we can strip of some characters by using \type {\doboundtext}. When the
+%D text is wider than the given width, it's split and the third argument is
+%D appended. When the text to be checked is packed in a command, we'll have to use
+%D \type {\expandafter}.
+%D
+%D \starttyping
+%D \doboundtext{a very, probably to long, text}{3cm}{...}
+%D \stoptyping
+%D
+%D When calculating the room needed, we take the width of the third argument into
+%D account, which leads to a bit more complex macro than needed at first sight.
+
+\def\dodoboundtext#1%
+ {\setbox\scratchboxone\hbox{#1}%
+ \advance\scratchdimen -\wd\scratchboxone
+ \ifdim\scratchdimen>\zeropoint\relax#1\fi}%
+
+\def\doboundtext#1#2#3% still used?
+ {\hbox
+ {\setbox\scratchbox\hbox{#1}%
+ \scratchdimen#2\relax
+ \ifdim\wd\scratchbox>\scratchdimen
+ \setbox\scratchbox\hbox{#3}%
+ \advance\scratchdimen -\wd\scratchbox
+ \handletokens#1\with\dodoboundtext
+ \fi
+ \box\scratchbox}}
+
+%D \macros
+%D {limitatetext}
+%D
+%D A bit more beautiful alternative for the previous command is the next one. This
+%D command is more robust because we let \TEX\ do most of the job. The previous
+%D command works better on text that cannot be hyphenated.
+%D
+%D \starttyping
+%D \limitatetext {text} {width} {sentinel}
+%D \limitatetext {text} {-width} {prelude}
+%D \stoptyping
+%D
+%D When no width is given, the whole text comes available. The sentinel is optional.
+%D This is about the third version.
+
+\ifdefined\fakecompoundhyphen\else \let\fakecompoundhyphen\relax \fi
+\ifdefined\veryraggedright \else \def\veryraggedright{\raggedright} \fi
+
+\unexpanded\def\limitatetext
+ {\bgroup % evt \setstrut
+ \forgetall % otherwise indentation and so
+ \let\limitatetext\firstofthreearguments
+ \fakecompoundhyphen % dangerous ! ! ! ! ! ! ! ! !
+ \dowithnextboxcs\syst_boxes_limitate_text\hbox}
+
+\def\syst_boxes_limitate_text#1% #2
+ {\doifelsenothing{#1}\syst_boxes_limitate_text_nop\syst_boxes_limitate_text_yes{#1}} % {#2}
+
+\def\syst_boxes_limitate_text_nop#1#2%
+ {\unhbox\nextbox
+ \egroup}
+
+\def\syst_boxes_limitate_text_yes#1#2%
+ {\nopenalties
+ \scratchdimen#1\relax
+ \ifdim\scratchdimen<\zeropoint\relax % we'll take the last line
+ \donefalse
+ \scratchdimen-\scratchdimen
+ \else
+ \donetrue
+ \fi
+ \ifdim\wd\nextbox>\scratchdimen
+ \setbox\scratchbox\hbox{\ifdone\space#2\else#2\space\fi}%
+ \advance\scratchdimen -\wd\scratchbox
+ \setbox\scratchboxone\box\nextbox
+ \setbox\nextbox\vbox
+ {\hsize\scratchdimen
+ \hfuzz\maxdimen
+ \veryraggedright
+ \strut
+ \ifdone \else
+ \parfillskip\zeropoint
+ \rightskip\zeropoint
+ \hskip\zeropoint \s!plus 1\s!fill % \hsize
+ \fi
+ \unhcopy\scratchboxone}%
+ \ifdim\ht\nextbox>\strutht
+ \setbox\nextbox\vbox % if omitted: missing brace reported
+ {\splittopskip\openstrutheight
+ \ifdone
+ \setbox\nextbox\vsplit\nextbox to \strutht
+ \else
+ \doloop
+ {\setbox\scratchboxone\vsplit\nextbox to \strutht
+ \ifdim\ht\nextbox>\strutht \else \exitloop \fi}%
+ \fi
+ \unvbox\nextbox
+ \setbox\nextbox\lastbox
+ \global\setbox1\hpack
+ {\ifdone
+ \unhbox\nextbox\unskip\kern\zeropoint\box\scratchbox
+ \else
+ \box\scratchbox\unhbox\nextbox
+ \fi
+ \unskip}}%
+ \unhbox1
+ \else
+ \unhbox0%
+ \fi
+ \else
+ \unhbox\nextbox
+ \fi
+ \egroup}
+
+%D We can also limit a text with more control:
+%D
+%D \startbuffer
+%D \limitatetext {\input tufte } {2cm,5mm} {\unknown}
+%D \limitatetext {ton en hans} {2cm,5mm} {\unknown}
+%D \limitatetext {ton en hans zijn eikels} {2cm,5mm} {\unknown}
+%D \limitatetext {ton} {2cm,5mm} {\unknown}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D We build this feature on top of the previous macro.
+
+% we could move the text argument to the end
+
+\let\normallimitatetext\limitatetext
+
+\def\speciallimitatetext#1#2#3#4% text left right placeholder
+ {%\dontleavehmode
+ \bgroup
+ \let\speciallimitatetext\firstoffourarguments
+ \setbox\scratchboxone\hbox
+ {\nohyphens
+ \normallimitatetext{#1}{+#2}{}#4%
+ \normallimitatetext{#1}{-#3}{}}%
+ \setbox\scratchboxtwo\hbox
+ {#1}%
+ \ifdim\wd\scratchboxtwo<\wd\scratchboxone #1\else\unhbox\scratchboxone\fi
+ \egroup}
+
+\unexpanded\def\limitatetext#1#2#3% \expanded added 2003/01/16
+ {\splitatcomma{#2}\leftlimit\rightlimit
+ \ifx\rightlimit\empty
+ \normallimitatetext {#1}\leftlimit {#3}%
+ \else
+ \speciallimitatetext{#1}\leftlimit\rightlimit{#3}%
+ \fi}
+
+%D Undocumented bonus (see wiki):
+%D
+%D \starttyping
+%D \limitatefirstline{\input tufte\relax}{10cm}{\unknown}
+%D \stoptyping
+
+\unexpanded\def\limitatefirstline#1#2#3%
+ {\hbox\bgroup\strut % \hpack
+ \setbox\scratchbox\hbox{\begstrut#1\endstrut}%
+ \ifdim\wd\scratchbox>#2\relax
+ \setbox\scratchbox\hbox{#3}%
+ \hsize#2\relax
+ \advance\hsize-\wd\scratchbox
+ \setbox\scratchbox\vbox{\forgetall\veryraggedright#1}%
+ \setbox\scratchbox\vsplit\scratchbox to \lineheight
+ \vbox
+ {\unvbox\scratchbox
+ \global\setbox\plusone\lastbox
+ \global\setbox\plusone\hbox{\strut\unhbox\plusone}%
+ \hbox % to #2 % \hpack
+ {\ifx\clip\undefined
+ \box\plusone
+ \orelse\ifdim\wd\plusone>\hsize
+ \lower\strutdepth\hpack{\clip[\c!width=\hsize,\c!height=\lineheight]{\hpack{\raise\strutdepth\box\plusone}}}%
+ \else
+ \box\plusone
+ \fi
+ \removeunwantedspaces#3}}% \removeunwantedspaces\hss#3}}%
+ \else
+ #1%
+ \fi
+ \egroup}
+
+%D \macros
+%D {processisolatedwords,processisolatedchars}
+%D
+%D \startbuffer
+%D \processisolatedchars{some more words} \ruledhbox \par
+%D \processisolatedchars{and some $x + y = z$ math} \ruledhbox \par
+%D \processisolatedchars{and a \hbox{$x + y = z$}} \ruledhbox \par
+%D \processisolatedwords{some more words} \ruledhbox \par
+%D \processisolatedwords{and some $x + y = z$ math} \ruledhbox \par
+%D \processisolatedwords{and a \hbox{$x + y = z$}} \ruledhbox \par
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+% todo: provide variant with #1 picked up as box
+
+\unexpanded\def\processisolatedchars#1#2%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
+ \setbox\scratchbox\hbox{\restorecurrentattributes{pic}#1}%
+ \clf_applytobox
+ method {char}%
+ box \scratchbox
+ command {\csstring#2}%
+ nested true%
+ \relax
+ \endgroup}
+
+\unexpanded\def\processisolatedwords#1#2%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
+ \setbox\scratchbox\hbox{\restorecurrentattributes{pic}#1}%
+ \clf_applytobox
+ method {word}%
+ box \scratchbox
+ command {\csstring#2}%
+ nested true%
+ \relax
+ \endgroup}
+
+%D A variant:
+
+\unexpanded\def\applytocharacters#1%
+ {\dontleavehmode
+ \dowithnextbox{\clf_applytobox
+ method {char}%
+ box \nextbox
+ command {\csstring#1}%
+ nested true%
+ \relax}%
+ \hbox}
+
+\unexpanded\def\applytowords#1%
+ {\dontleavehmode
+ \dowithnextbox{\clf_applytobox
+ method {word}%
+ box \nextbox
+ command {\csstring#1}%
+ nested true%
+ \relax}%
+ \hbox}
+
+%D The old call:
+
+\unexpanded\def\processwords#1%
+ {\processisolatedwords{#1}\processword}
+
+\let\processword\relax
+
+\unexpanded\def\applytosplitstringchar#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {char}%
+ \relax}
+
+\unexpanded\def\applytosplitstringword#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {word}%
+ \relax}
+
+\unexpanded\def\applytosplitstringline#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {line}%
+ \relax}
+
+\unexpanded\def\applytosplitstringcharspaced#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {char}%
+ spaced true%
+ \relax}
+
+\unexpanded\def\applytosplitstringwordspaced#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {word}%
+ spaced true%
+ \relax}
+
+\unexpanded\def\applytosplitstringlinespaced#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {line}%
+ spaced true%
+ \relax}
+
+%D \macros
+%D {sbox}
+%D
+%D This is a rather strange command. It grabs some box content and and limits the
+%D size to the height and depth of a \type {\strut}. The resulting bottom||alligned
+%D box can be used aside other ones, without disturbing the normal baseline
+%D distance.
+%D
+%D \startbuffer
+%D \ruledhbox to .5\hsize{\sbox{eerste\par tweede \par derde}}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Shows up as:
+%D
+%D \startexample
+%D \vskip3\baselineskip
+%D \getbuffer
+%D \stopexample
+%D
+%D Before displaying the result we added some skip, otherwise the first two lines
+%D would have ended up in the text. This macro can be useful when building
+%D complicated menus, headers and footers and|/|or margin material.
+
+\unexpanded\def\sbox
+ {\vbox\bgroup
+ \dowithnextboxcs\syst_boxes_sbox_finish\vbox}
+
+\unexpanded\def\syst_boxes_sbox_finish
+ {\setbox\nextbox\hpack
+ {\strut
+ \dp\nextbox\zeropoint
+ \lower\strutdp\box\nextbox}%
+ \dp\nextbox\strutdp
+ \ht\nextbox\strutht
+ \box\nextbox
+ \egroup}
+
+%D A variant on this:
+
+\unexpanded\def\inlinedbox
+ {\bgroup
+ \dowithnextbox
+ {\setbox\nextbox\hpack
+ {\lower
+ \dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax
+ \box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}%
+ \hbox}
+
+%D \macros
+%D {struttedbox}
+%D
+%D This boxing macro limits the height and depth to those of a strut.
+
+\unexpanded\def\struttedbox
+ {\hpack\bgroup
+ \dowithnextboxcs\syst_boxes_struttedbox_finish\hbox}
+
+\def\syst_boxes_struttedbox_finish
+ {\dp\nextbox\strutdepth
+ \ht\nextbox\strutheight
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {topskippedbox}
+%D
+%D This macro compensates the difference between the topskip and strutheight. Watch
+%D how we preserve the depth when it equals strutdepth.
+
+\unexpanded\def\topskippedbox
+ {\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox}
+
+\def\syst_boxes_topskippedbox_finish
+ {\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}%
+ \lower\topskip\hpack{\raise\strutheight\box\nextbox}%
+ \m_boxes_tmp
+ \egroup}
+
+%D \macros
+%D {centeredbox, centerednextbox}
+%D
+%D Here is another strange one. This one offers a sort of overlay with positive or
+%D negative offsets. This command can be used in well defined areas where no offset
+%D options are available. We first used it when building a button inside the margin
+%D footer, where the button should have a horizontal offset and should be centered
+%D with respect to the surrounding box. The last of the three examples we show below
+%D says:
+%D
+%D \starttyping
+%D \vsize=3cm
+%D \hsize=3cm
+%D \ruledvbox to \vsize
+%D {\centeredbox height .5cm width -1cm
+%D {\vrule width \hsize height \vsize}}}
+%D \stoptyping
+%D
+%D Here the \type {\ruledvbox} just shows the surrounding box and \type {\vrule} is
+%D used to show the centered box.
+%D
+%D \def\AnExample#1#2%
+%D {\vsize=3cm
+%D \hsize=3cm
+%D \ruledvbox to \vsize
+%D {\centeredbox height #1 width #2
+%D {\color[green]{\vrule width \hsize height \vsize}}}}
+%D
+%D \startlinecorrection
+%D \startcombination[3*1]
+%D {\AnExample {-1cm} {.5cm}} {}
+%D {\AnExample {.5cm} {-1cm}} {}
+%D {\AnExample {-1cm} {-.5cm}} {}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D This command takes two optional arguments: \type {width} and \type {height}.
+%D Observing readers can see that we use \TEX's own scanner for grabbing these
+%D arguments: \type {#1#} reads everyting till the next brace and passes it to both
+%D rules. The setting of the box dimensions at the end is needed for special cases.
+%D The dimensions of the surrounding box are kept intact. This commands handles
+%D positive and negative dimensions (which is why we need two boxes with rules).
+
+\unexpanded\def\centeredbox#1#% height +/-dimen width +/-dimen
+ {\bgroup
+ \setbox\scratchboxone\vpack to \vsize
+ \bgroup
+ \dontcomplain
+ \forgetall
+ \setbox\scratchboxone\hpack{\vrule\s!width \zeropoint#1}%
+ \setbox\scratchboxtwo\vpack{\hrule\s!height\zeropoint#1}%
+ \advance\vsize \ht\scratchboxtwo
+ \advance\hsize \wd\scratchboxone
+ \vpack to \vsize
+ \bgroup
+ \vskip-\ht\scratchboxtwo
+ \vss
+ \hpack to \hsize
+ \bgroup
+ \dowithnextbox
+ {\hskip-\wd\scratchboxone
+ \hss
+ \box\nextbox
+ \hss
+ \egroup
+ \vss
+ \egroup
+ \egroup
+ \wd\scratchboxone\hsize
+ \ht\scratchboxone\vsize
+ \box\scratchboxone
+ \egroup}
+ \hbox}
+
+%D For those who don't want to deal with \type {\hsize} and \type {\vsize}, we have:
+%D
+%D \starttyping
+%D \centerednextbox width 2bp height 2bp
+%D {\framed[width=100bp,height=100bp]{}}
+%D \stoptyping
+%D
+%D Do you see what we call this one \type {next}?
+
+\unexpanded\def\centerednextbox#1#%
+ {\bgroup
+ \dowithnextbox
+ {\hsize\wd\nextbox
+ \vsize\ht\nextbox
+ \centeredbox#1{\box\nextbox}%
+ \egroup}
+ \hbox}
+
+%D \macros
+%D {centerbox}
+%D
+%D Centering on the available space is done by:
+%D
+%D \starttyping
+%D \centerbox <optional specs> {content}
+%D \stoptyping
+%D
+%D When omitted, the current \type {\hsize} and \type {\vsize} are used. Local
+%D dimensions are supported.
+
+\unexpanded\def\centerbox#1#% optional height +/-dimen width +/-dimen
+ {\bgroup
+ \dowithnextbox
+ {\setlocalhsize
+ \setbox\scratchbox\hpack{\vrule\s!width \zeropoint#1}%
+ \ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi
+ \setbox\scratchbox\vpack{\hrule\s!height\zeropoint#1}%
+ \ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi
+ \vpack to \vsize{\vss\hpack to \hsize{\hss\box\nextbox\hss}\vss}%
+ \egroup}%
+ \hbox}
+
+%D \macros
+%D {setrigidcolumnhsize,rigidcolumnbalance,rigidcolumnlines}
+%D
+%D These macros are copied from the \TEX book, page~397, and extended by a macro
+%D that sets the \type {\hsize}.
+%D
+%D \starttyping
+%D \setrigidcolumnhsize {total width} {distance} {n}
+%D \rigidcolumnbalance {box}
+%D \stoptyping
+%D
+%D Both these macros are for instance used in typesetting footnotes. The following
+%D flags influence the process.
+
+\newif\ifalignrigidcolumns
+\newif\ifstretchrigidcolumns
+\newif\iftightrigidcolumns % if true: just a vbox, no depth/noflines/gridsnap corrrections
+
+\unexpanded\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr
+ {\xdef\savedrigidhsize{\the\hsize}%
+ \hsize#1\relax
+ \global\chardef\rigidcolumns#3\relax
+ \scratchdimen -#2\relax
+ \multiply\scratchdimen #3\relax
+ \advance\scratchdimen #2\relax
+ \advance\hsize \scratchdimen
+ \divide\hsize #3\relax}
+
+% ==
+%
+% \def\setrigidcolumnhsize#1#2#3%
+% {\xdef\savedrigidhsize{\the\hsize}%
+% \global\chardef\rigidcolumns#3\relax
+% \hsize=\dimexpr(#1-\numexpr#3-1\relax\dimexpr#2\relax)/#3\relax}
+
+\newbox\rigidcolumnbox
+
+\let\rigidcolumnlines\!!zerocount
+
+\unexpanded\def\rigidcolumnbalance#1%
+ {\ifnum\rigidcolumns=1 % tzt ook h/d correctie
+ \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax
+ \else
+ \vbox % \vpack
+ {\forgetall
+ \nopenalties
+ \dontcomplain
+ \setbox\rigidcolumnbox\vbox
+ {\line{}\goodbreak\unvbox#1\removebottomthings}%
+ \splittopskip\openstrutheight
+ \setbox\scratchbox\vsplit\rigidcolumnbox to \zeropoint
+ \ifcase\rigidcolumnlines\relax
+ % \iffalse
+ % % maybe some day an option
+ % \scratchskip\ht\rigidcolumnbox
+ % \advance\scratchskip\dp\rigidcolumnbox
+ % \getnoflines\scratchskip
+ % \ifodd\noflines
+ % \advance\noflines\plusone
+ % \fi
+ % \divide\noflines\rigidcolumns
+ %\else
+ \scratchdimen\ht\rigidcolumnbox
+ \divide\scratchdimen \rigidcolumns
+ \getnoflines\scratchdimen
+ %\fi
+ \else
+ \noflines\rigidcolumnlines % to be sure
+ \fi
+ \scratchdimen\noflines\lineheight
+ % new: we now loop so that we don't loose content
+ % since in practice we also use this macro for
+ % funny lineheights and border cases
+ \setbox0=\box\rigidcolumnbox
+ \doloop
+ {\setbox\rigidcolumnbox=\copy0
+ \setbox\scratchbox\hpack to \savedrigidhsize
+ {\dorecurse\rigidcolumns
+ {\setbox\scratchbox\vsplit\rigidcolumnbox to \scratchdimen
+ \dp\scratchbox\openstrutdepth
+ \setbox\scratchbox\vtop
+ \ifalignrigidcolumns to
+ \ifstretchrigidcolumns\vsize\else\scratchdimen\fi
+ \fi
+ {\unvbox\scratchbox}%
+ \wd\scratchbox\hsize
+ \box\scratchbox
+ \hfill}%
+ \hfillneg}%
+ \ifvoid\rigidcolumnbox\exitloop\else\advance\scratchdimen\lineheight\fi}%
+ \iftightrigidcolumns
+ \setbox\scratchbox\hpack{\raise\dp\scratchbox\box\scratchbox}%
+ \else
+ \advance\scratchdimen -\openstrutdepth
+ \setbox\scratchbox\hpack{\raise\scratchdimen\box\scratchbox}%
+ \dp\scratchbox\openstrutdepth
+ \ht\scratchbox\scratchdimen
+ \fi
+ \box\scratchbox}%
+ \fi}
+
+%D \macros
+%D {startvboxtohbox,stopvboxtohbox,convertvboxtohbox}
+%D
+%D Here is another of Knuth's dirty tricks, as presented on pages 398 and 399 of the
+%D \TEX book. These macros can be used like:
+%D
+%D \starttyping
+%D \vbox
+%D \bgroup
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \egroup
+%D
+%D \vbox
+%D \bgroup
+%D \convertvboxtohbox
+%D \egroup
+%D \stoptyping
+%D
+%D These macros are used in reformatting footnotes, so they do what they're meant
+%D for.
+
+\newdimen\vboxtohboxslack
+\newdimen\hboxestohboxslack
+
+%D Create line and fake height of paragraph by messign with heights: a nice hack by
+%D DEK himself. See older files for that code.
+
+% \definesystemattribute[vboxtohboxseparator][public]
+
+%newbox\d_syst_boxes_vboxtohbox
+\newbox\d_syst_boxes_separator
+
+\unexpanded\def\startvboxtohboxseparator
+ {\setbox\d_syst_boxes_separator\hbox attr \vboxtohboxseparatorattribute\plusone\bgroup}
+
+\unexpanded\def\stopvboxtohboxseparator
+ {\egroup}
+
+\unexpanded\def\startvboxtohbox
+ {\begingroup
+ \setbox\scratchbox\hbox\bgroup}
+
+\unexpanded\def\stopvboxtohbox
+ {\ifvoid\d_syst_boxes_separator
+ \hskip\zeropoint\ifcase\vboxtohboxslack\else\s!minus\vboxtohboxslack\fi % we really need a skip
+ \else
+ \box\d_syst_boxes_separator
+ \fi
+ \egroup
+ \clf_hboxtovbox\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+% A possible reconstruction:
+
+\unexpanded\def\convertvboxtohbox
+ {\makehboxofhboxes
+ \setbox\scratchboxone\hpack{\unhbox\scratchboxone\removehboxes}% \hpack
+ \noindent\unhbox\scratchboxone\par}
+
+\unexpanded\def\makehboxofhboxes
+ {\setbox\scratchboxone\emptyhbox
+ \loop % \doloop { .. \exitloop .. }
+ \setbox\scratchboxtwo\lastbox
+ \ifhbox\scratchboxtwo
+ \setbox\scratchboxone\hpack{\box\scratchboxtwo\unhbox\scratchboxone}%
+ \repeat}
+
+\unexpanded\def\removehboxes
+ {\setbox\scratchboxone\lastbox
+ \ifhbox\scratchboxone
+ {\removehboxes}\unhbox\scratchboxone
+ \fi}
+
+% And one special for notes:
+
+\unexpanded\def\starthboxestohbox
+ {\bgroup
+ \setbox\scratchbox\vbox\bgroup}
+
+\unexpanded\def\stophboxestohbox
+ {\egroup
+ \clf_vboxlisttohbox\scratchbox\nextbox\dimexpr\hboxestohboxslack\relax
+ \dontleavehmode
+ \unhbox\nextbox
+ \removeunwantedspaces
+ \par
+ \egroup}
+
+%D \macros
+%D {unhhbox}
+%D
+%D The next macro is used in typesetting inline headings. Let's first look at the
+%D macro and then show an example.
+
+\newbox \unhhedbox
+\newbox \hhbox
+\newdimen \lasthhboxwidth
+\newskip \hhboxindent
+
+\unexpanded\def\unhhbox#1\with#2%
+ {\bgroup
+ \nopenalties
+ \dontcomplain
+ \forgetall
+ \setbox\unhhedbox\vbox{\hskip\hhboxindent\strut\unhbox#1}% => \hsize
+ \doloop
+ {\setbox\hhbox\vsplit\unhhedbox to \lineheight
+ \ifvoid\unhhedbox
+ \setbox\hhbox\hbox{\strut\hboxofvbox\hhbox}% \hpack
+ \fi
+ \ht\hhbox\strutht
+ \dp\hhbox\strutdp
+ \ifzeropt\hhboxindent\else % \ifdim\hhboxindent=\zeropoint\else
+ \setbox\hhbox\hpack{\kern-\hhboxindent\box\hhbox}%
+ \hhboxindent\zeropoint
+ \fi
+ \global\lasthhboxwidth\wd\hhbox
+ #2\relax
+ \ifvoid\unhhedbox
+ \exitloop
+ \else
+ \hskip\zeropoint \s!plus \zeropoint
+ \fi}%
+ \egroup}
+
+\def\dohboxofvbox
+ {\setbox0\vpack{\unvbox\scratchcounter\global\setbox1\lastbox}%
+ \unhbox1
+ \egroup}
+
+\unexpanded\def\hboxofvbox
+ {\bgroup
+ \afterassignment\dohboxofvbox
+ \scratchcounter=}
+
+%D This macro can be used to break a paragraph apart and treat each line seperately,
+%D for instance, making it clickable. The main complication is that we want to be
+%D able to continue the paragraph, something that's needed in the in line section
+%D headers.
+%D
+%D \startbuffer
+%D \setbox0=\hbox{\input tufte \relax}
+%D \setbox2=\hbox{\input knuth \relax}
+%D \unhhbox0\with{\ruledhbox{\box\hhbox}}
+%D \hskip1em plus 1em minus 1em
+%D \hhboxindent=\lasthhboxwidth
+%D \advance\hhboxindent by \lastskip
+%D \unhhbox2\with{\ruledhbox{\box\hhbox}}
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D This piece of text was typeset by saying:
+%D
+%D \typebuffer
+%D
+%D Not that nice a definition, but effective. Note the stretch we've build in the
+%D line that connects the two paragraphs.
+
+%D \macros
+%D {doifcontent}
+%D
+%D When processing depends on the availability of content, one can give the next
+%D macro a try.
+%D
+%D \starttyping
+%D \doifcontent{pre content}{post content}{no content}\somebox
+%D \stoptyping
+%D
+%D Where \type {\somebox} is either a \type {\hbox} or \type {\vbox}. If the
+%D dimension of this box suggest some content, the resulting box is unboxed and
+%D surrounded by the first two arguments, else the third arguments is executed.
+
+\unexpanded\def\doifcontent#1#2#3%
+ {\dowithnextbox
+ {\ifhbox\nextbox
+ \ifdim\wd\nextbox>\zeropoint
+ #1\unhbox\nextbox#2\relax
+ \else
+ #3\relax
+ \fi
+ \else
+ \ifdim\ht\nextbox>\zeropoint
+ #1\unvbox\nextbox#2\relax
+ \else
+ #3\relax
+ \fi
+ \fi}}
+
+%D So when we say:
+%D
+%D \startbuffer
+%D \doifcontent{[}{]}{}\hbox{content sensitive typesetting}
+%D
+%D \doifcontent{}{\page}{}\vbox{content sensitive typesetting}
+%D
+%D \doifcontent{}{}{\message{Didn't you forget something?}}\hbox{}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D We get:
+%D
+%D \getbuffer
+%D
+%D Where the last call of course does not show up in this document, but definitely
+%D generates a confusing message.
+
+%D \macros
+%D {processboxes}
+%D
+%D The next macro gobble boxes and is for instance used for overlays. First we show
+%D the general handler.
+
+\newbox\processbox % public : this is the one where \nextbox's end up in
+
+\unexpanded\def\processboxes#1%
+ {\bgroup
+ \def\syst_boxes_process_indeed{#1}% #1 can be redefined halfway
+ \setbox\processbox\emptybox
+ \doifelsenextbgroup\syst_boxes_process_yes\syst_boxes_process_nop}
+
+\def\syst_boxes_process_yes
+ {\dowithnextboxcs\syst_boxes_process_content\hbox}
+
+\def\syst_boxes_process_content
+ {\removeunwantedspaces
+ \syst_boxes_process_indeed % takes \nextbox makes \processbox
+ \doifelsenextbgroup\syst_boxes_process_yes\syst_boxes_process_nop}
+
+\unexpanded\def\syst_boxes_process_nop
+ {\removeunwantedspaces
+ \box\processbox
+ \egroup}
+
+%D \macros
+%D {startoverlay}
+%D
+%D We can overlay boxes by saying:
+%D
+%D \startbuffer
+%D \startoverlay
+%D {\framed{hans}}
+%D {\framed[width=3cm]{ton}}
+%D {\framed[height=2cm]{oeps}}
+%D \stopoverlay
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows up as:
+%D
+%D \leavevmode\getbuffer
+
+\def\boxisempty#1%
+ {\ifdim\wd#1=\zeropoint
+ \ifdim\ht#1=\zeropoint
+ \ifdim\dp#1=\zeropoint
+ \zerocount
+ \else
+ \plusone
+ \fi
+ \else
+ \plusone
+ \fi
+ \else
+ \plusone
+ \fi}
+
+\def\syst_boxes_overlay_process
+ {\ifcase\boxisempty\nextbox\else
+ \syst_boxes_overlay_process_indeed
+ \fi}
+
+\def\syst_boxes_overlay_process_indeed
+ {%\removeunwantedspaces % already done
+ \scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi
+ \ifdim\ht\nextbox>\ht\processbox
+ \setbox\processbox\vpack to \ht\nextbox {\dp\processbox\zeropoint\vss\box\processbox\vss}%
+ \else
+ \setbox\nextbox \vpack to \ht\processbox{\dp\nextbox \zeropoint\vss\box\nextbox \vss}%
+ \fi
+ \dp\nextbox \scratchdepth
+ \dp\processbox\scratchdepth
+ \scratchwidth\wd\ifdim\wd\nextbox>\wd\processbox\nextbox\else\processbox\fi
+ \setbox\processbox\hpack to \scratchwidth
+ {\hpack to \scratchwidth{\hss\box\processbox\hss}%
+ \kern-\scratchwidth
+ \hpack to \scratchwidth{\hss\box\nextbox \hss}}}
+
+\unexpanded\def\startoverlay
+ {\bgroup
+ \let\stopoverlay\egroup
+ \processboxes\syst_boxes_overlay_process}
+
+\let\stopoverlay\relax
+
+%D \macros
+%D {fakebox}
+%D
+%D The next macro is a rather silly one, but saves space.
+%D
+%D \starttyping
+%D \hbox{\fakebox0}
+%D \stoptyping
+%D
+%D returns an empty box with the dimensions of the box specified, here being zero.
+
+\unexpanded\def\fakebox
+ {\bgroup
+ \afterassignment\syst_boxes_fakebox_finish\scratchcounter}
+
+\def\syst_boxes_fakebox_finish
+ {\setbox\scratchbox\ifhbox\scratchcounter\emptyhbox\else\emptyvbox\fi
+ \wd\scratchbox\wd\scratchcounter
+ \ht\scratchbox\ht\scratchcounter
+ \dp\scratchbox\dp\scratchcounter
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {lbox,rbox,cbox,tbox,bbox}
+%D
+%D Here are some convenient alternative box types:
+%D
+%D \starttyping
+%D \lbox{text ...}
+%D \cbox{text ...}
+%D \rbox{text ...}
+%D \stoptyping
+%D
+%D Are similar to \type {\vbox}, which means that they also accept something like
+%D \type {to 3cm}, but align to the left, middle and right. These box types can be
+%D used to typeset paragraphs.
+
+\def\syst_boxes_lrc_process#1{\bgroup\forgetall\let\\\endgraf#1\let\next}
+
+\unexpanded\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft }
+\unexpanded\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter}
+\unexpanded\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright }
+
+\unexpanded\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft }
+\unexpanded\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter}
+\unexpanded\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright }
+
+%D The alternatives \type {\tbox} and \type {\bbox} can be used to properly align
+%D boxes, like in:
+%D
+%D \setupexternalfigures[directory={../sample}]
+%D \startbuffer
+%D \starttable[|||]
+%D \HL
+%D \VL \tbox{\externalfigure[cow][height=3cm,frame=on]} \VL top aligned \VL\SR
+%D \HL
+%D \VL \bbox{\externalfigure[cow][height=3cm,frame=on]} \VL bottom aligned \VL\SR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D The positioning depends on the strut settings:
+%D
+%D \getbuffer
+
+\unexpanded\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox}
+\unexpanded\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox}
+
+\def\syst_boxes_tbox_finish
+ {\scratchdepth\dimexpr\ht\nextbox+\dp\nextbox-\ht\strutbox\relax
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\scratchdepth
+ \setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}%
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
+
+\def\syst_boxes_bbox_finish
+ {\scratchheight\dimexpr\ht\nextbox+\dp\nextbox-\dp\strutbox\relax
+ \dp\nextbox\dp\strutbox
+ \ht\nextbox\scratchheight
+ \setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}%
+ \dp\nextbox\dp\strutbox
+ \ht\nextbox\scratchheight
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {lhbox,mhbox,rhbox}
+%D
+%D A few more boxes.
+
+\def\dodolhbox{\hpack to \hsize{\box\nextbox\hss }}
+\def\dodomhbox{\hpack to \hsize{\hss\box\nextbox\hss}}
+\def\dodorhbox{\hpack to \hsize{\hss\box\nextbox }}
+
+\unexpanded\def\lhbox{\dowithnextboxcs\dodolhbox\hbox}
+\unexpanded\def\mhbox{\dowithnextboxcs\dodomhbox\hbox}
+\unexpanded\def\rhbox{\dowithnextboxcs\dodorhbox\hbox}
+
+\let\lefthbox \lhbox
+\let\midhbox \mhbox
+\let\righthbox\rhbox
+
+%D \macros
+%D {boxofsize}
+%D
+%D Sometimes we need to construct a box with a height or width made up of several
+%D dimensions. Instead of cumbersome additions, we can use:
+%D
+%D \starttyping
+%D \boxofsize \vbox 10cm 3cm -5cm {the text to be typeset}
+%D \stoptyping
+%D
+%D This example demonstrates that one can use positive and negative values.
+%D Dimension registers are also accepted.
+
+\newdimen\sizeofbox
+
+\unexpanded\def\boxofsize#1%
+ {\bgroup
+ \sizeofbox\zeropoint
+ \scratchdimen\zeropoint
+ \def\docommand
+ {\advance\sizeofbox\scratchdimen
+ \futurelet\next\dodocommand}%
+ \def\dodocommand
+ {\ifx\next\bgroup
+ \expanded{\egroup#1 to \the\sizeofbox}%
+ \else
+ \expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen
+ \fi}%
+ \docommand}
+
+%D Some new, still undocumented features:
+
+% limitatetext -> beter {text} als laatste !!
+%
+% \limitvbox
+% \limithbox
+
+\unexpanded\def\limitatelines#1#2% size sentinel
+ {\dowithnextbox
+ {\dimen0=#1\hsize
+ \ifdim\wd\nextbox>\dimen0
+ \setbox\nextbox\hbox
+ {\advance\dimen0 -.1\hsize
+ \limitatetext{\unhbox\nextbox}{\dimen0}{\nobreak#2}}%
+ \fi
+ \unhbox\nextbox}
+ \hbox}
+
+\unexpanded\def\fittoptobaselinegrid % weg hier
+ {\dowithnextbox
+ {\bgroup
+ \par
+ \dimen0\ht\nextbox
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \hpack{\box\nextbox}
+ \prevdepth\strutdp
+ \doloop
+ {\advance\dimen0 -\lineheight
+ \ifdim\dimen0<\zeropoint
+ \exitloop
+ \else
+ \nobreak
+ \hpack{\strut}
+ \fi}
+ \egroup}
+ \vbox}
+
+%D Some more undocumented macros (used in m-chart).
+
+\newif\iftraceboxplacement % \traceboxplacementtrue
+
+\newbox\fakedboxcursor
+
+\setbox\fakedboxcursor\hpack
+ {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
+
+\unexpanded\def\boxcursor % overloaded in core-vis
+ {\iftraceboxplacement
+ \bgroup
+ \scratchdimen2\onepoint
+ \setbox\scratchbox\hpack to \zeropoint
+ {\hss
+ \vrule
+ \s!width \scratchdimen
+ \s!height\scratchdimen
+ \s!depth \scratchdimen
+ \hss}%
+ \smashedbox\scratchbox
+ \egroup
+ \else
+ \copy\fakedboxcursor
+ \fi}
+
+\unexpanded\def\placedbox
+ {\iftraceboxplacement\ruledhbox\else\hbox\fi}
+
+\newdimen\boxoffset
+\newdimen\boxhdisplacement
+\newdimen\boxvdisplacement
+
+\unexpanded\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox}
+\unexpanded\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox}
+\unexpanded\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox}
+\unexpanded\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox}
+\unexpanded\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox}
+\unexpanded\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox}
+\unexpanded\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox}
+\unexpanded\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox}
+
+\let\topleftbox \lefttopbox
+\let\toprightbox \righttopbox
+\let\bottomleftbox \leftbottombox
+\let\bottomrightbox\rightbottombox
+
+\def\syst_boxes_rightbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_leftbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_topbox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_bottombox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_lefttopbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_righttopbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_leftbottombox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_rightbottombox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\unexpanded\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox}
+\unexpanded\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox}
+\unexpanded\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox}
+\unexpanded\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox}
+
+\def\syst_boxes_middlebox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselinemiddlebox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselineleftbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselinerightbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+%D \macros
+%D {obox}
+%D
+%D Experimental, not yet frozen:
+
+\unexpanded\def\lrtbbox#1#2#3#4% l r t b
+ {\bgroup
+ \dowithnextboxcontent
+ {\advance\hsize-#1\advance\hsize-#2\relax
+ \advance\vsize-#3\advance\vsize-#4\relax}
+ {\forgetall\vpack to \vsize{\vskip#3\hpack to \hsize{\hskip#1\box\nextbox\hss}\vss}\egroup}
+ \vbox}
+
+%D \macros
+%D {toplinebox}
+%D
+%D See core-tbl.tex for an example of its usage:
+
+\unexpanded\def\toplinebox
+ {\dowithnextboxcs\syst_boxes_toplinebox_finish\tbox}
+
+\def\syst_boxes_toplinebox_finish
+ {\ifdim\dp\nextbox>\strutdepth
+ \scratchdimen\dp\nextbox
+ \advance\scratchdimen-\strutdepth
+ \getnoflines\scratchdimen
+ \struttedbox{\box\nextbox}%
+ \dorecurse\noflines\verticalstrut
+ \else
+ \box\nextbox
+ \fi}
+
+%D \macros
+%D {initializeboxstack,savebox,foundbox}
+%D
+%D At the cost of some memory, but saving box registers, we have implemented a box
+%D repository.
+%D
+%D \starttyping
+%D \initializeboxstack{one}
+%D
+%D \savebox{one}{a}{test a}
+%D \savebox{one}{p}{test p}
+%D \savebox{one}{q}{test q}
+%D
+%D \hbox{a:\foundbox{one}{a}} \par
+%D \hbox{q:\foundbox{one}{q}} \par
+%D \hbox{p:\foundbox{one}{p}} \par
+%D \hbox{x:\foundbox{one}{x}} \par
+%D \hbox{y:\foundbox{two}{a}} \par
+%D \stoptyping
+
+%D Kind of obsolete:
+
+\installcorenamespace {stackbox}
+\installcorenamespace {stacklst}
+
+\unexpanded\def\setstackbox#1#2%
+ {\ifcsname\??stackbox#1:#2\endcsname\else
+ \expandafter\newbox\csname\??stackbox#1:#2\endcsname
+ \fi
+ \global\setbox\csname\??stackbox#1:#2\endcsname\vbox}
+
+\unexpanded\def\initializeboxstack#1%
+ {\def\docommand##1{\setstackbox{#1}{##1}{}}%
+ \ifcsname\??stacklst#1\endcsname
+ \expandafter\processcommacommand\expandafter[\lastnamedcs]\docommand
+ \fi
+ \letgvalueempty{\??stacklst#1}}
+
+\unexpanded\def\savebox#1#2% stack name
+ {% beware, \setxvalue defines the cs beforehand so we cannot use the
+ % test inside the { }
+ \ifcsname\??stacklst#1\endcsname
+ %\setxvalue{\??stacklst#1}{\csname\??stacklst#1\endcsname,#2}%
+ \expandafter\xdef\csname\??stacklst#1\expandafter\endcsname\expandafter{\lastnamedcs,#2}%
+ \else
+ \expandafter\xdef\csname\??stacklst#1\endcsname{#2}%
+ \fi
+ \setstackbox{#1}{#2}}
+
+\unexpanded\def\flushbox#1#2% unwrapped
+ {\ifcsname\??stackbox#1:#2\endcsname
+ \box\lastnamedcs
+ \else
+ \emptybox
+ \fi}
+
+\unexpanded\def\restorebox#1#2% unwrapped
+ {\ifcsname\??stackbox#1:#2\endcsname
+ \copy\lastnamedcs
+ \else
+ \emptybox
+ \fi}
+
+\unexpanded\def\foundbox#1#2% wrapped
+ {\vpack
+ {\ifcsname\??stackbox#1:#2\endcsname
+ \copy\lastnamedcs
+ \fi}}
+
+\unexpanded\def\doifelsebox#1#2%
+ {\ifcsname\??stackbox#1:#2\endcsname
+ \ifvoid\lastnamedcs
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifboxelse\doifelsebox
+
+%D This one is cheaper (the above is no longer used that much):
+
+\installcorenamespace {boxstack}
+
+\newcount\c_syst_boxes_stack
+\let \b_syst_boxes_stack\relax
+
+\unexpanded\def\syst_boxes_stack_allocate
+ {\newbox\b_syst_boxes_stack
+ \expandafter\let\csname\??boxstack\number\c_syst_boxes_stack\endcsname\b_syst_boxes_stack}
+
+\unexpanded\def\syst_boxes_push#1#2%
+ {\global\advance\c_syst_boxes_stack\plusone
+ \expandafter\let\expandafter\b_syst_boxes_stack\csname\??boxstack\number\c_syst_boxes_stack\endcsname
+ \ifx\b_syst_boxes_stack\relax % cheaper then csname check as in most cases it's defined
+ \syst_boxes_stack_allocate
+ \fi
+ #1\setbox\b_syst_boxes_stack\box#2\relax}
+
+\unexpanded\def\syst_boxes_pop#1#2%
+ {#1\setbox#2\box\csname\??boxstack\number\c_syst_boxes_stack\endcsname
+ \global\advance\c_syst_boxes_stack\minusone}
+
+\unexpanded\def\localpushbox {\syst_boxes_push\relax}
+\unexpanded\def\localpopbox {\syst_boxes_pop \relax}
+
+\unexpanded\def\globalpushbox{\syst_boxes_push\global}
+\unexpanded\def\globalpopbox {\syst_boxes_pop \global}
+
+%D And here is a more modern one (not yet in i-*):
+%D
+%D \starttyping
+%D \dorecurse {100} {
+%D \setbox\zerocount\hbox{test \recurselevel}
+%D \putboxincache{foo}{\recurselevel}\zerocount
+%D \copyboxfromcache{foo}{\recurselevel}\zerocount
+%D \iftrue
+%D \setbox\zerocount\hbox{\directboxfromcache{foo}{\recurselevel}}%
+%D \else
+%D \getboxfromcache{foo}{\recurselevel}\zerocount
+%D \fi
+%D }
+%D \resetboxesincache{foo}
+%D \stoptyping
+
+\unexpanded\def\putboxincache #1#2#3{\clf_putboxincache {#1}{#2}#3\relax}
+\unexpanded\def\getboxfromcache #1#2#3{\clf_getboxfromcache {#1}{#2}#3\relax}
+\unexpanded\def\doifelseboxincache #1#2{\clf_doifelseboxincache {#1}{#2}}
+\unexpanded\def\copyboxfromcache #1#2#3{\clf_copyboxfromcache {#1}{#2}#3\relax}
+\unexpanded\def\directboxfromcache #1#2{\clf_directboxfromcache {#1}{#2}}
+\unexpanded\def\directcopyboxfromcache#1#2{\clf_directcopyboxfromcache{#1}{#2}}
+\unexpanded\def\resetboxesincache #1{\clf_resetboxesincache {#1}}
+
+\unexpanded\def\putnextboxincache#1#2%
+ {\dowithnextbox{\putboxincache{#1}{#2}\nextbox}}
+
+%D \macros
+%D {removedepth, obeydepth}
+%D
+%D While \type {\removedepth} removes the preceding depth, \type {\obeydepth} makes
+%D sure we have depth. Both macros leave the \type {\prevdepth} untouched.
+
+\unexpanded\def\removedepth
+ {\ifvmode
+ \ifdim\prevdepth>\zeropoint
+ \kern-\prevdepth
+ \fi
+ \fi}
+
+\unexpanded\def\obeydepth
+ {\par % watch out for changes in math formulas
+ \ifvmode\ifdim\prevdepth<\zeropoint\orelse\ifdim\prevdepth<\strutdp
+ \kern\dimexpr\strutdp-\prevdepth\relax
+ \prevdepth\strutdp
+ \fi\fi}
+
+\unexpanded\def\undepthed
+ {\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\hbox}
+
+%D \macros
+%D {removebottomthings, removelastskip}
+%D
+%D A funny (but rather stupid) one, plus a redefinition.
+
+\unexpanded\def\removebottomthings
+ {\dorecurse\plusfive{\unskip\unkern\unpenalty}}
+
+\unexpanded\def\removelastskip % \ifvmode the plain tex one \fi
+ {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
+
+%D \macros
+%D {makestrutofbox}
+%D
+%D This macro sets the dimensions of a box to those of a strut. Sort of obsolete so
+%D it will go away.
+
+\unexpanded\def\makestrutofbox % not used
+ {\afterassignment\syst_boxes_makestrutofbox\c_boxes_register}
+
+\def\syst_boxes_makestrutofbox
+ {\ht\c_boxes_register\strutht
+ \dp\c_boxes_register\strutdp
+ \wd\c_boxes_register\zeropoint}
+
+%D \macros
+%D {raisebox,lowerbox}
+%D
+%D Some more box stuff, related to positioning (under construction). Nice stuff for
+%D a tips and tricks maps article.
+%D
+%D \starttyping
+%D \raisebox{100pt}\hbox{test}
+%D \hsmash{\raisebox{100pt}\hbox{test}}
+%D \stoptyping
+
+\unexpanded\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
+\unexpanded\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
+
+\def\syst_boxes_raise_indeed{\dowithnextboxcs\syst_boxes_raise_finish}
+\def\syst_boxes_lower_indeed{\dowithnextboxcs\syst_boxes_lower_finish}
+
+\def\syst_boxes_raise_finish
+ {\setbox\nextbox\hpack{\raise\scratchdimen\box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}
+
+\def\syst_boxes_lower_finish
+ {\setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}
+
+% vcenter in text, we kunnen vcenter overloaden
+
+\unexpanded\def\halfwaybox
+ {\hpack\bgroup
+ \dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox}
+
+\def\syst_boxes_halfwaybox_finish
+ {\dp\nextbox\zeropoint
+ \lower.5\ht\nextbox\box\nextbox
+ \egroup}
+
+\unexpanded\def\depthonlybox
+ {\tpack\bgroup
+ \dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox}
+
+\def\syst_boxes_depthonlybox_finish
+ {\hsize\wd\nextbox
+ \kern\zeropoint\box\nextbox
+ \egroup}
+
+%D New:
+
+\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi}
+\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi}
+
+%D And even rawer:
+
+\let\naturalvcenter\normalvtop % will go away
+
+%D \macros
+%D {vcenter}
+%D
+%D Also new: tex mode \type {\vcenter}.
+
+\unexpanded\def\vcenter
+ {\vbox\bgroup
+ \dowithnextboxcs\syst_boxes_vcenter_finish\vbox}
+
+\def\syst_boxes_vcenter_finish
+ {\hpack{\normalstartimath\vcenter{\box\nextbox}\normalstopimath}%
+ \egroup}
+
+% could be \everymathematics
+
+\prependtoks \let\vcenter\normalvcenter \to \everymath
+\prependtoks \let\vcenter\normalvcenter \to \everydisplay
+
+% \appendtoks \let\vcenter\normalvcenter \to \everymathematics
+
+%D \macros
+%D {frozenhbox}
+%D
+%D A not so well unhboxable box can be made with:
+
+\unexpanded\def\frozenhbox
+ {\hpack\bgroup
+ \dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox}
+
+\def\syst_boxes_frozenhbox_finish
+ {\hpack{\hpack{\box\nextbox}}%
+ \egroup}
+
+%D \macros
+%D {setboxllx,setboxlly,gsetboxllx,gsetboxlly,getboxllx,getboxlly}
+%D
+%D A prelude to an extended \TEX\ feature:
+
+\installcorenamespace {box_x}
+\installcorenamespace {box_y}
+
+\unexpanded\def\setboxllx #1#2{\expandafter\edef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
+\unexpanded\def\setboxlly #1#2{\expandafter\edef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
+
+\unexpanded\def\gsetboxllx#1#2{\expandafter\xdef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
+\unexpanded\def\gsetboxlly#1#2{\expandafter\xdef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
+
+%def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\csname\??box_x\number#1\endcsname\else\zeropoint\fi}
+%def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\csname\??box_y\number#1\endcsname\else\zeropoint\fi}
+\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+
+\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence
+\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence
+
+%D \macros
+%D {shownextbox}
+%D
+%D Handy for tracing
+%D
+%D \starttyping
+%D \shownextbox\vbox{test}
+%D \shownextbox\vbox{test\endgraf}
+%D \shownextbox\vbox{test\endgraf\strut\endgraf}
+%D \shownextbox\vbox{test\endgraf\thinrule}
+%D \shownextbox\vbox{\setupwhitespace[big]test\endgraf\thinrule}
+%D \stoptyping
+
+\unexpanded\def\shownextbox % seldom used
+ {\dowithnextbox
+ {\bgroup
+ \showboxbreadth\maxdimen
+ \showboxdepth \maxdimen
+ \scratchcounter\interactionmode
+ \batchmode
+ \showbox\nextbox
+ \box\nextbox
+ \interactionmode\scratchcounter
+ \egroup}}
+
+\unexpanded\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>}
+ {\bgroup
+ \ifhbox#1\relax
+ \setbox\scratchboxtwo\emptybox
+ \unhbox#1%
+ \doloop
+ {\unpenalty\unskip\unpenalty\unskip\unpenalty\unskip
+ \setbox\scratchboxone\lastbox
+ \ifvoid\scratchboxone
+ \exitloop
+ \else
+ \setbox\scratchboxtwo\hbox
+ {\ifhbox\scratchboxone \spreadhbox\scratchboxone\else\box\scratchboxone\fi
+ \ifvoid\scratchboxtwo \else\hss\unhbox\scratchboxtwo\fi}%
+ \fi}%
+ \ifvoid\scratchboxtwo\else\unhbox\scratchboxtwo\fi
+ \else
+ \box#1%
+ \fi
+ \egroup}
+
+% makes sense but too much log for overfull boxes:
+%
+% \showboxbreadth\maxdimen
+% \showboxdepth \maxdimen
+
+%D Moved from cont-new:
+%D
+%D \starttyping
+%D \minimalhbox 100pt {test}
+%D \stoptyping
+
+\unexpanded\def\minimalhbox#1#%
+ {\dowithnextbox
+ {\bgroup
+ \setbox\scratchbox\hpack#1{\hss}%
+ \ifdim\wd\nextbox<\wd\scratchbox\wd\nextbox\wd\scratchbox\fi
+ \box\nextbox
+ \egroup}
+ \hbox}
+
+%D A bit dirty:
+
+% \unexpanded\def\nodestostring#1% \cs {content}
+% {\dowithnextbox{\edef#1{\syst_boxes_nodestostring}}\hbox}
+%
+% \def\syst_boxes_nodestostring
+% {\clf_boxtostring\nextbox}
+
+\unexpanded\def\nodestostring#1#2% more tolerant for #2=\cs
+ {\begingroup
+ \setbox\nextbox\hbox{#2}%
+ \normalexpanded{\endgroup\edef\noexpand#1{\clf_boxtostring\nextbox}}}
+
+%D Even more dirty:
+
+\let\hyphenatedhbox\hbox
+
+%D We can do this:
+%D
+%D \starttyping
+%D \setbox0\hbox to 10cm{foo} \setbox2\hbox{\unhbox0} \the\wd2
+%D \stoptyping
+%D
+%D But this saves a copy (and hpack pass):
+%D
+%D \starttyping
+%D \setbox0\hbox to 10cm{foo} \the\naturalwd0
+%D \stoptyping
+
+\newdimen\lastnaturalboxwd
+\newdimen\lastnaturalboxht
+\newdimen\lastnaturalboxdp
+
+\let\getnaturaldimensions\clf_getnaturaldimensions % sets three dimensions
+\let\naturalwd \clf_naturalwd % calculates and returns wd
+
+\let\getnaturalwd\clf_getnaturalwd % no intermediate
+\let\setnaturalwd\clf_setnaturalwd % no intermediate
+
+\unexpanded\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox}
+
+\let\doifrighttoleftinboxelse\doifelserighttoleftinbox
+
+%D New, used in high/low:
+
+\definesystemattribute [runningtext] [public]
+
+%unexpanded\def\runninghbox{\hbox attr \runningtextattribute \plusone} % not yet in i-*
+\unexpanded\def\runninghbox{\hbox attr \runningtextattribute \fontid\font} % not yet in i-*
+
+%D To complement lua (yet undocumented):
+
+\unexpanded\def\beginhbox{\hbox\bgroup} \let\endhbox\egroup
+\unexpanded\def\beginvbox{\vbox\bgroup} \let\endvbox\egroup
+\unexpanded\def\beginvtop{\vtop\bgroup} \let\endvtop\egroup
+
+\unexpanded\def\sethboxregister#1{\setbox#1\hbox}
+\unexpanded\def\setvboxregister#1{\setbox#1\vbox}
+\unexpanded\def\setvtopregister#1{\setbox#1\vtop}
+
+\unexpanded\def\flushboxregister#1{\box\numexpr#1\relax}
+
+\unexpanded\def\starthboxregister#1{\setbox#1\hbox\bgroup} \let\stophboxregister\egroup
+\unexpanded\def\startvboxregister#1{\setbox#1\vbox\bgroup} \let\stopvboxregister\egroup
+\unexpanded\def\startvtopregister#1{\setbox#1\vtop\bgroup} \let\stopvtopregister\egroup
+
+%D For whatever third party package needs it:
+%D
+%D \starttyping
+%D \newlocalbox\BoxOne
+%D \newlocalbox\BoxTwo
+%D
+%D \setbox\BoxOne\hbox{Box One}
+%D \setbox\BoxTwo\hbox{Box Two}
+%D
+%D [\box\BoxTwo] [\box\BoxOne]
+%D \stoptyping
+
+\installcorenamespace{localbox}
+
+\unexpanded\def\newlocalbox#1%
+ {\expandafter\let\expandafter#1\csname\??localbox\string#1\endcsname
+ \ifx#1\relax
+ \syst_aux_new_localbox#1%
+ \fi}
+
+\def\syst_aux_new_localbox#1%
+ {\expandafter\newbox\csname\??localbox\string#1\endcsname
+ \newlocalbox#1}
+
+%D Who knows when this comes in handy:
+
+\unexpanded\def\lastlinewidth{\dimexpr\clf_lastlinewidth\scaledpoint\relax}
+
+%D Keep as reference:
+
+% \unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox}
+% \unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop}
+
+%D This one keeps dimensions and sets the shift field (and so it's more for testing
+%D than for real usage):
+
+\unexpanded\def\shiftbox{\clf_shiftbox}
+
+%D This one has been moved from a 2 decade old file. It makes something boxed
+%D sit on the baseline.
+
+\unexpanded\def\linebox
+ {\hpack\bgroup\dowithnextbox
+ {\scratchdimen\dimexpr\dimexpr\htdp\nextbox-\lineheight\relax/2+\dp\strutbox\relax
+ \setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}%
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\dp\strutbox
+ \box\nextbox
+ \egroup}
+ \hbox}
+
+\protect \endinput
+
+% a bit of test code:
+
+% \hbox \bgroup
+% \ruledvbox {\hbox{\strut gans}}
+% \ruledvbox to \lineheight {\hbox{\strut gans}}
+% \ruledvbox to \lineheight {\hbox {gans}}
+% \ruledvbox to \strutheight{\hbox {gans}}
+% \ruledvbox to \strutheight{\hbox{\strut gans}}
+% \ruledvbox to \strutheight{\vss\hbox{gans}}
+% \egroup
+
+% to be considered
+
+% \startluacode
+%
+% local spacer = lpeg.patterns.spacer
+%
+% function commands.withwords(command,str)
+% if str then
+% command = command or "ruledhbox"
+% local done = false
+% local function apply(s)
+% if done then
+% context.space()
+% done = true
+% else
+% context.dontleavehmode()
+% end
+% context[command](s)
+% end
+% lpeg.match(lpeg.splitter(spacer,apply),str)
+% end
+%
+% end
+%
+% \stopluacode
+%
+% \unprotect
+%
+% \unexpanded\def\withwordsinstring#1#2% command str
+% {\ctxcommand{withwords(\!!bs#1\!!es,\!!bs#2\!!es)}}
+%
+% \unexpanded\def\withwordsinfile#1#2% command name
+% {\ctxcommand{withwords(\!!bs#1\!!es,io.loaddata(resolvers.findfile("#2")))}}
+%
+% \protect
+%
+% \starttext
+%
+% \defineframed[colored][foregroundcolor=red,foregroundstyle=\bfc\underbar,location=low]
+%
+% \withwordsinstring{colored}{bla bla}
+% \withwordsinfile{colored}{ward.tex}
+%
+% \stoptext
diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv
index 8336800fc..f6b094246 100644
--- a/tex/context/base/mkiv/syst-aux.mkiv
+++ b/tex/context/base/mkiv/syst-aux.mkiv
@@ -11,11 +11,6 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D There are some references to \LUA\ variants here but these concern (often old)
-%D experiments, moved from local test modules to here, cleaned up, but not really
-%D used. After all it's not that urgent and replacing helpers is a delicate process.
-%D Don't depend on it.
-
\registerctxluafile{syst-aux}{}
% A dedicated primitive \ifvoidmacro\cs == \ifx\cs\empty is some 10% faster but
@@ -76,20 +71,6 @@
\fi
-% %D \macros
-% %D {expunded}
-% %D
-% %D \unexpanded\edef\TestA{zzz}
-% %D \edef\TestB{zzz}
-% %D
-% %D \doifelse {\TestA} {\TestB} {WRONG} {OKAY} \par
-% %D \doifelse {\TestA} {\expunded\TestB} {WRONG} {OKAY} \par
-% %D \doifelse {\expunded\TestA} {\TestB} {OKAY} {WRONG} \par
-% %D \doifelse {\expunded\TestA} {\expunded\TestB} {OKAY} {WRONG} \par
-
-% %def\expunded#1{\normalexpanded\expandafter{#1}}
-% \def\expunded#1{\expandafter\empty#1} % used within an edef anyway
-
%D As we don't have namespace definers yet, we use a special one:
\ifdefined\c_syst_helpers_n_of_namespaces
@@ -315,33 +296,17 @@
\expandafter\m_syst_action_nop
\fi}
-\startmkivmode
-
- \unexpanded\def\doifelsenextchar#1#2#3% #1 should not be {} !
- {\let\charactertoken=#1% = needed here
- \def\m_syst_action_yes{#2}%
- \def\m_syst_action_nop{#3}%
- \futurelet\nexttoken\syst_helpers_inspect_next_character}
+\unexpanded\def\doifelsenextchar#1#2#3% #1 should not be {} !
+ {\let\charactertoken=#1% = needed here
+ \def\m_syst_action_yes{#2}%
+ \def\m_syst_action_nop{#3}%
+ \futurelet\nexttoken\syst_helpers_inspect_next_character}
- \unexpanded\def\doifelsenextcharcs#1#2#3% #1 should not be {} !
- {\let\charactertoken=#1% = needed here
- \let\m_syst_action_yes#2%
- \let\m_syst_action_nop#3%
- \futurelet\nexttoken\syst_helpers_inspect_next_character}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifelsenextchar#1#2#3% #1 should not be {} !
- {\def\m_syst_action_yes{#2}%
- \def\m_syst_action_nop{#3}%
- \futureexpandis#1\m_syst_action_yes\m_syst_action_nop}
-
- \unexpanded\def\doifelsenextcharcs % #1#2#3% #1 should not be {} !
- {\futureexpandis}
-
-\stoplmtxmode
+\unexpanded\def\doifelsenextcharcs#1#2#3% #1 should not be {} !
+ {\let\charactertoken=#1% = needed here
+ \let\m_syst_action_yes#2%
+ \let\m_syst_action_nop#3%
+ \futurelet\nexttoken\syst_helpers_inspect_next_character}
\let\doifnextcharelse \doifelsenextchar
\let\doifnextcharcselse\doifelsenextcharcs
@@ -378,33 +343,17 @@
\expandafter\m_syst_action_nop
\fi}
-\startmkivmode
-
- \unexpanded\def\doifelsenextoptional#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \unexpanded\def\doifelsenextoptionalcs#1#2% \cs \cs (upto 10% faster)
- {\let\m_syst_action_yes#1%
- \let\m_syst_action_nop#2%
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifelsenextoptional#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \futureexpandis[\m_syst_action_yes\m_syst_action_nop}
-
- \unexpanded\def\doifelsenextoptionalcs
- {\futureexpandis[}
+\unexpanded\def\doifelsenextoptional#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\stoplmtxmode
+\unexpanded\def\doifelsenextoptionalcs#1#2% \cs \cs (upto 10% faster)
+ {\let\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
\let\doifnextoptionalelse \doifelsenextoptional
\let\doifnextoptionalcselse\doifelsenextoptionalcs
@@ -437,33 +386,17 @@
\expandafter\m_syst_action_nop
\fi}
-\startmkivmode
-
- \unexpanded\def\doifelsenextbgroup#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
-
- \unexpanded\def\doifelsenextbgroupcs#1#2%
- {\let\m_syst_action_yes#1%
- \let\m_syst_action_nop#2%
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifelsenextbgroup#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \futureexpandis\bgroup\m_syst_action_yes\m_syst_action_nop}
-
- \unexpanded\def\doifelsenextbgroupcs % #1#2
- {\futureexpandis\bgroup}
+\unexpanded\def\doifelsenextbgroup#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
-\stoplmtxmode
+\unexpanded\def\doifelsenextbgroupcs#1#2%
+ {\let\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
\let\doifnextbgroupelse \doifelsenextbgroup
\let\doifnextbgroupcselse\doifelsenextbgroupcs
@@ -484,24 +417,11 @@
\expandafter\m_syst_action_nop
\fi}
-\startmkivmode
-
- \unexpanded\def\doifelsenextparenthesis#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifelsenextparenthesis#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \futureexpandis(\m_syst_action_yes\m_syst_action_nop}
-
-\stoplmtxmode
+\unexpanded\def\doifelsenextparenthesis#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
\let\doifnextparenthesiselse\doifelsenextparenthesis
@@ -514,31 +434,15 @@
\expandafter\m_syst_action_nop
\fi}
-\startmkivmode
-
- \unexpanded\def\doifelsefastoptionalcheck#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
-
- \unexpanded\def\doifelsefastoptionalcheckcs#1#2% \cs \cs
- {\let\m_syst_action_yes#1%
- \let\m_syst_action_nop#2%
- \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifelsefastoptionalcheck#1#2%
- {\def\m_syst_action_yes{#1}%
- \def\m_syst_action_nop{#2}%
- \futureexpandis[\m_syst_action_yes\m_syst_action_nop}
-
- \unexpanded\def\doifelsefastoptionalcheckcs
- {\futureexpandis[}
+\unexpanded\def\doifelsefastoptionalcheck#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
-\stoplmtxmode
+\unexpanded\def\doifelsefastoptionalcheckcs#1#2% \cs \cs
+ {\let\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
+ \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
\let\doiffastoptionalcheckelse \doifelsefastoptionalcheck
\let\doiffastoptionalcheckcselse\doifelsefastoptionalcheckcs
@@ -816,61 +720,32 @@
%D \doifelse {string1} {string2} {then ...}{else ...}
%D \stoptyping
-\startmkivmode
-
- \unexpanded\def\doif#1#2%
- {\edef\m_syst_string_one{#1}%
- \edef\m_syst_string_two{#2}%
- \ifx\m_syst_string_one\m_syst_string_two
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
-
- \unexpanded\def\doifnot#1#2%
- {\edef\m_syst_string_one{#1}%
- \edef\m_syst_string_two{#2}%
- \ifx\m_syst_string_one\m_syst_string_two
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
-
- \unexpanded\def\doifelse#1#2%
- {\edef\m_syst_string_one{#1}%
- \edef\m_syst_string_two{#2}%
- \ifx\m_syst_string_one\m_syst_string_two
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifelse#1#2%
- {\iftok{#1}{#2}%
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
- \unexpanded\def\doif#1#2%
- {\iftok{#1}{#2}%
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
+\unexpanded\def\doif#1#2%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
- \unexpanded\def\doifnot#1#2%
- {\iftok{#1}{#2}%
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
+\unexpanded\def\doifnot#1#2%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
-\stoplmtxmode
+\unexpanded\def\doifelse#1#2%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
%D \macros
%D {doifempty,doifemptyelse,doifnotempty}
@@ -1648,55 +1523,26 @@
%D The macro accepts \type {123}, \type {abc}, \type {{}}, \type {\getal} and \type
%D {\the\count...}. This macro is a rather dirty one.
-\startmkivmode
-
- \def\doifelsenumber#1% does not accept counters (fully expandable)
- {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
- \expandafter\secondoftwoarguments
- \else
- \expandafter\firstoftwoarguments
- \fi}
-
- \def\doifnumber#1%
- {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
-
- \def\doifnotnumber#1%
- {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \def\doifelsenumber#1%
- {\ifchknum#1\or
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
- \def\doifnumber#1%
- {\ifchknum#1\or
- \expandafter\firstoftwoarguments
- \else
- \expandafter\gobbleoneargument
- \fi}
+\def\doifelsenumber#1% does not accept counters (fully expandable)
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
- \def\doifnotnumber#1%
- {\ifchknum#1\or
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
+\def\doifnumber#1%
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
-\stoplmtxmode
+\def\doifnotnumber#1%
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
\let\doifnumberelse\doifelsenumber
@@ -2494,22 +2340,18 @@
%
% But we use this as it keeps the original name visible:
-\startmkivmode
-
- \def\syst_helpers_empty_spaced_six {\the\t_syst_aux[][][][][][] }
- \def\syst_helpers_empty_normal_six {\the\t_syst_aux[][][][][][]}
- \def\syst_helpers_empty_spaced_five {\the\t_syst_aux[][][][][] }
- \def\syst_helpers_empty_normal_five {\the\t_syst_aux[][][][][]}
- \def\syst_helpers_empty_spaced_four {\the\t_syst_aux[][][][] }
- \def\syst_helpers_empty_normal_four {\the\t_syst_aux[][][][]}
- \def\syst_helpers_empty_spaced_three{\the\t_syst_aux[][][] }
- \def\syst_helpers_empty_normal_three{\the\t_syst_aux[][][]}
- \def\syst_helpers_empty_spaced_two {\the\t_syst_aux[][] }
- \def\syst_helpers_empty_normal_two {\the\t_syst_aux[][]}
- \def\syst_helpers_empty_spaced_one {\the\t_syst_aux[] }
- \def\syst_helpers_empty_normal_one {\the\t_syst_aux[]}
-
-\stopmkivmode
+\def\syst_helpers_empty_spaced_six {\the\t_syst_aux[][][][][][] }
+\def\syst_helpers_empty_normal_six {\the\t_syst_aux[][][][][][]}
+\def\syst_helpers_empty_spaced_five {\the\t_syst_aux[][][][][] }
+\def\syst_helpers_empty_normal_five {\the\t_syst_aux[][][][][]}
+\def\syst_helpers_empty_spaced_four {\the\t_syst_aux[][][][] }
+\def\syst_helpers_empty_normal_four {\the\t_syst_aux[][][][]}
+\def\syst_helpers_empty_spaced_three{\the\t_syst_aux[][][] }
+\def\syst_helpers_empty_normal_three{\the\t_syst_aux[][][]}
+\def\syst_helpers_empty_spaced_two {\the\t_syst_aux[][] }
+\def\syst_helpers_empty_normal_two {\the\t_syst_aux[][]}
+\def\syst_helpers_empty_spaced_one {\the\t_syst_aux[] }
+\def\syst_helpers_empty_normal_one {\the\t_syst_aux[]}
\def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux}
\def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux}
@@ -2531,34 +2373,17 @@
% {\firstargumentfalse
% #1[]}
-\startmkivmode
+\unexpanded\def\dosingleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_single_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_single_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
- \unexpanded\def\dosingleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \let\m_syst_action_yes\syst_helpers_single_empty_one_yes
- \let\m_syst_action_nop\syst_helpers_single_empty_one_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_single_empty_one_nop
- {\firstargumentfalse
- \the\t_syst_aux[]}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\dosingleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop}
-
- \def\syst_helpers_single_empty_one_nop
- {\firstargumentfalse
- \the\t_syst_aux[]}
-
-\stoplmtxmode
+\def\syst_helpers_single_empty_one_nop
+ {\firstargumentfalse
+ \the\t_syst_aux[]}
%D Double
@@ -2590,61 +2415,34 @@
% \def\syst_helpers_double_empty_one_spaced#1#2{#1[{#2}][] }
% \def\syst_helpers_double_empty_one_normal#1#2{#1[{#2}][]}
-\startmkivmode
-
- \unexpanded\def\dodoubleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \let\m_syst_action_yes\syst_helpers_double_empty_one_yes
- \let\m_syst_action_nop\syst_helpers_double_empty_one_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_double_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_double_empty_two_yes
- \let\m_syst_action_nop\syst_helpers_double_empty_two_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_double_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \the\t_syst_aux[][]}
-
- \def\syst_helpers_double_empty_two_nop
- {\secondargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_one
- \else
- \expandafter\syst_helpers_empty_normal_one
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\dodoubleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop}
-
- \def\syst_helpers_double_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop}
-
- \def\syst_helpers_double_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \the\t_syst_aux[][]}
-
- \def\syst_helpers_double_empty_two_nop
- {\secondargumentfalse
- \the\t_syst_aux[]}
-
-\stoplmtxmode
+\unexpanded\def\dodoubleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_double_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_double_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_double_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_double_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_double_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_double_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \the\t_syst_aux[][]}
+
+\def\syst_helpers_double_empty_two_nop
+ {\secondargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_one
+ \else
+ \expandafter\syst_helpers_empty_normal_one
+ \fi}
% Triple
@@ -2694,90 +2492,52 @@
% \def\syst_helpers_triple_empty_three_spaced#1#2#3{#1[{#2}][{#3}][] }
% \def\syst_helpers_triple_empty_three_normal#1#2#3{#1[{#2}][{#3}][]}
-\startmkivmode
-
- \unexpanded\def\dotripleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \let\m_syst_action_yes\syst_helpers_triple_empty_one_yes
- \let\m_syst_action_nop\syst_helpers_triple_empty_one_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_triple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_triple_empty_two_yes
- \let\m_syst_action_nop\syst_helpers_triple_empty_two_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_triple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_triple_empty_three_yes
- \let\m_syst_action_nop\syst_helpers_triple_empty_three_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_triple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux[][][]}
-
- \def\syst_helpers_triple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_two
- \else
- \expandafter\syst_helpers_empty_normal_two
- \fi}
-
- \def\syst_helpers_triple_empty_three_nop
- {\thirdargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_one
- \else
- \expandafter\syst_helpers_empty_normal_one
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\dotripleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop}
-
- \def\syst_helpers_triple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop}
-
- \def\syst_helpers_triple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop}
-
- \def\syst_helpers_triple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux[][][]}
-
- \def\syst_helpers_triple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux[][]}
-
- \def\syst_helpers_triple_empty_three_nop
- {\thirdargumentfalse
- \the\t_syst_aux[]}
+\unexpanded\def\dotripleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_triple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_triple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_triple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_triple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_triple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_triple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_triple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_triple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_triple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \the\t_syst_aux[][][]}
+
+\def\syst_helpers_triple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_two
+ \else
+ \expandafter\syst_helpers_empty_normal_two
+ \fi}
-\stoplmtxmode
+\def\syst_helpers_triple_empty_three_nop
+ {\thirdargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_one
+ \else
+ \expandafter\syst_helpers_empty_normal_one
+ \fi}
%D Quadruple:
@@ -2846,121 +2606,71 @@
% \def\syst_helpers_quadruple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][] }
% \def\syst_helpers_quadruple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][]}
-\startmkivmode
-
- \unexpanded\def\doquadrupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \let\m_syst_action_yes\syst_helpers_quadruple_empty_one_yes
- \let\m_syst_action_nop\syst_helpers_quadruple_empty_one_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quadruple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_quadruple_empty_two_yes
- \let\m_syst_action_nop\syst_helpers_quadruple_empty_two_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quadruple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_quadruple_empty_three_yes
- \let\m_syst_action_nop\syst_helpers_quadruple_empty_three_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quadruple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_quadruple_empty_four_yes
- \let\m_syst_action_nop\syst_helpers_quadruple_empty_four_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quadruple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux[][][][]}
-
- \def\syst_helpers_quadruple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_three
- \else
- \expandafter\syst_helpers_empty_normal_three
- \fi}
-
- \def\syst_helpers_quadruple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_two
- \else
- \expandafter\syst_helpers_empty_normal_two
- \fi}
-
- \def\syst_helpers_quadruple_empty_four_nop
- {\fourthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_one
- \else
- \expandafter\syst_helpers_empty_normal_one
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doquadrupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop}
-
- \def\syst_helpers_quadruple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop}
-
- \def\syst_helpers_quadruple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop}
-
- \def\syst_helpers_quadruple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop}
-
- \def\syst_helpers_quadruple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux[][][][]}
-
- \def\syst_helpers_quadruple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux[][][]}
-
- \def\syst_helpers_quadruple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux[][]}
+\unexpanded\def\doquadrupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quadruple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quadruple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quadruple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quadruple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \the\t_syst_aux[][][][]}
+
+\def\syst_helpers_quadruple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_three
+ \else
+ \expandafter\syst_helpers_empty_normal_three
+ \fi}
- \def\syst_helpers_quadruple_empty_four_nop
- {\fourthargumentfalse
- \the\t_syst_aux[]}
+\def\syst_helpers_quadruple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_two
+ \else
+ \expandafter\syst_helpers_empty_normal_two
+ \fi}
-\stoplmtxmode
+\def\syst_helpers_quadruple_empty_four_nop
+ {\fourthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_one
+ \else
+ \expandafter\syst_helpers_empty_normal_one
+ \fi}
%D Quintuple:
@@ -3049,154 +2759,91 @@
% \def\syst_helpers_quintuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][] }
% \def\syst_helpers_quintuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][]}
-\startmkivmode
-
- \unexpanded\def\doquintupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \let\m_syst_action_yes\syst_helpers_quintuple_empty_one_yes
- \let\m_syst_action_nop\syst_helpers_quintuple_empty_one_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quintuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_quintuple_empty_two_yes
- \let\m_syst_action_nop\syst_helpers_quintuple_empty_two_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quintuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_quintuple_empty_three_yes
- \let\m_syst_action_nop\syst_helpers_quintuple_empty_three_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quintuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_quintuple_empty_four_yes
- \let\m_syst_action_nop\syst_helpers_quintuple_empty_four_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quintuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_quintuple_empty_five_yes
- \let\m_syst_action_nop\syst_helpers_quintuple_empty_five_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_quintuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][][][][]}
-
- \def\syst_helpers_quintuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_four
- \else
- \expandafter\syst_helpers_empty_normal_four
- \fi}
-
- \def\syst_helpers_quintuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_three
- \else
- \expandafter\syst_helpers_empty_normal_three
- \fi}
+\unexpanded\def\doquintupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quintuple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quintuple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quintuple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quintuple_empty_four_yes[#1]%
+ {\fourthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_five_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_five_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_quintuple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux[][][][][]}
+
+\def\syst_helpers_quintuple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_four
+ \else
+ \expandafter\syst_helpers_empty_normal_four
+ \fi}
- \def\syst_helpers_quintuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_two
- \else
- \expandafter\syst_helpers_empty_normal_two
- \fi}
+\def\syst_helpers_quintuple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_three
+ \else
+ \expandafter\syst_helpers_empty_normal_three
+ \fi}
- \def\syst_helpers_quintuple_empty_five_nop
- {\fifthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_one
- \else
- \expandafter\syst_helpers_empty_normal_one
- \fi}
+\def\syst_helpers_quintuple_empty_four_nop
+ {\fourthargumentfalse
+ \fifthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_two
+ \else
+ \expandafter\syst_helpers_empty_normal_two
+ \fi}
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doquintupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop}
-
- \def\syst_helpers_quintuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop}
-
- \def\syst_helpers_quintuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop}
-
- \def\syst_helpers_quintuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop}
-
- \def\syst_helpers_quintuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop}
-
- \def\syst_helpers_quintuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][][][][]}
-
- \def\syst_helpers_quintuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][][][]}
-
- \def\syst_helpers_quintuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][][]}
-
- \def\syst_helpers_quintuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][]}
-
- \def\syst_helpers_quintuple_empty_five_nop
- {\fifthargumentfalse
- \the\t_syst_aux[]}
-
-\stoplmtxmode
+\def\syst_helpers_quintuple_empty_five_nop
+ {\fifthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_one
+ \else
+ \expandafter\syst_helpers_empty_normal_one
+ \fi}
%D Sixtuple:
@@ -3306,189 +2953,112 @@
% \def\syst_helpers_sixtuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][] }
% \def\syst_helpers_sixtuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][]}
-\startmkivmode
-
- \unexpanded\def\dosixtupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \let\m_syst_action_yes\syst_helpers_sixtuple_empty_one_yes
- \let\m_syst_action_nop\syst_helpers_sixtuple_empty_one_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_sixtuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_sixtuple_empty_two_yes
- \let\m_syst_action_nop\syst_helpers_sixtuple_empty_two_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_sixtuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_sixtuple_empty_three_yes
- \let\m_syst_action_nop\syst_helpers_sixtuple_empty_three_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_sixtuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_sixtuple_empty_four_yes
- \let\m_syst_action_nop\syst_helpers_sixtuple_empty_four_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_sixtuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_sixtuple_empty_five_yes
- \let\m_syst_action_nop\syst_helpers_sixtuple_empty_five_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_sixtuple_empty_five_yes[#1]%
- {\fifthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_sixtuple_empty_six_yes
- \let\m_syst_action_nop\syst_helpers_sixtuple_empty_six_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_sixtuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][][][][]}
-
- \def\syst_helpers_sixtuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_five
- \else
- \expandafter\syst_helpers_empty_normal_five
- \fi}
-
- \def\syst_helpers_sixtuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_four
- \else
- \expandafter\syst_helpers_empty_normal_four
- \fi}
+\unexpanded\def\dosixtupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_sixtuple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_sixtuple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_sixtuple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_sixtuple_empty_four_yes[#1]%
+ {\fourthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_five_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_five_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_sixtuple_empty_five_yes[#1]%
+ {\fifthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_six_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_six_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_sixtuple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \the\t_syst_aux[][][][][][]}
+
+\def\syst_helpers_sixtuple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_five
+ \else
+ \expandafter\syst_helpers_empty_normal_five
+ \fi}
- \def\syst_helpers_sixtuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_three
- \else
- \expandafter\syst_helpers_empty_normal_three
- \fi}
+\def\syst_helpers_sixtuple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_four
+ \else
+ \expandafter\syst_helpers_empty_normal_four
+ \fi}
- \def\syst_helpers_sixtuple_empty_five_nop
- {\fifthargumentfalse
- \sixthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_two
- \else
- \expandafter\syst_helpers_empty_normal_two
- \fi}
+\def\syst_helpers_sixtuple_empty_four_nop
+ {\fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_three
+ \else
+ \expandafter\syst_helpers_empty_normal_three
+ \fi}
- \def\syst_helpers_sixtuple_empty_six_nop
- {\sixthargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_one
- \else
- \expandafter\syst_helpers_empty_normal_one
- \fi}
+\def\syst_helpers_sixtuple_empty_five_nop
+ {\fifthargumentfalse
+ \sixthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_two
+ \else
+ \expandafter\syst_helpers_empty_normal_two
+ \fi}
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\dosixtupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop}
-
- \def\syst_helpers_sixtuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop}
-
- \def\syst_helpers_sixtuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop}
-
- \def\syst_helpers_sixtuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop}
-
- \def\syst_helpers_sixtuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop}
-
- \def\syst_helpers_sixtuple_empty_five_yes[#1]%
- {\fifthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop}
-
- \def\syst_helpers_sixtuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][][][][]}
-
- \def\syst_helpers_sixtuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][][][]}
-
- \def\syst_helpers_sixtuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][][]}
-
- \def\syst_helpers_sixtuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][]}
-
- \def\syst_helpers_sixtuple_empty_five_nop
- {\fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][]}
-
- \def\syst_helpers_sixtuple_empty_six_nop
- {\sixthargumentfalse
- \the\t_syst_aux[]}
-
-\stoplmtxmode
+\def\syst_helpers_sixtuple_empty_six_nop
+ {\sixthargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_one
+ \else
+ \expandafter\syst_helpers_empty_normal_one
+ \fi}
%D Seventuple:
@@ -3620,226 +3190,134 @@
% \def\syst_helpers_seventuple_empty_seven_spaced#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][] }
% \def\syst_helpers_seventuple_empty_seven_normal#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][]}
-\startmkivmode
-
- \unexpanded\def\doseventupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \let\m_syst_action_yes\syst_helpers_seventuple_empty_one_yes
- \let\m_syst_action_nop\syst_helpers_seventuple_empty_one_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_seventuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_seventuple_empty_two_yes
- \let\m_syst_action_nop\syst_helpers_seventuple_empty_two_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_seventuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_seventuple_empty_three_yes
- \let\m_syst_action_nop\syst_helpers_seventuple_empty_three_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_seventuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_seventuple_empty_four_yes
- \let\m_syst_action_nop\syst_helpers_seventuple_empty_four_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_seventuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_seventuple_empty_five_yes
- \let\m_syst_action_nop\syst_helpers_seventuple_empty_five_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_seventuple_empty_five_yes[#1]%
- {\fifthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_seventuple_empty_six_yes
- \let\m_syst_action_nop\syst_helpers_seventuple_empty_six_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_seventuple_empty_six_yes[#1]%
- {\sixthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \let\m_syst_action_yes\syst_helpers_seventuple_empty_seven_yes
- \let\m_syst_action_nop\syst_helpers_seventuple_empty_seven_nop
- \let\if_next_blank_space_token\iffalse
- \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-
- \def\syst_helpers_seventuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][][][][]}
-
- \def\syst_helpers_seventuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_six
- \else
- \expandafter\syst_helpers_empty_normal_six
- \fi}
-
- \def\syst_helpers_seventuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_five
- \else
- \expandafter\syst_helpers_empty_normal_five
- \fi}
+\unexpanded\def\doseventupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_seventuple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_seventuple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_seventuple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_seventuple_empty_four_yes[#1]%
+ {\fourthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_five_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_five_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_seventuple_empty_five_yes[#1]%
+ {\fifthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_six_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_six_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_seventuple_empty_six_yes[#1]%
+ {\sixthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_seven_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_seven_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_seventuple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \the\t_syst_aux[][][][][][][]}
+
+\def\syst_helpers_seventuple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_six
+ \else
+ \expandafter\syst_helpers_empty_normal_six
+ \fi}
- \def\syst_helpers_seventuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_four
- \else
- \expandafter\syst_helpers_empty_normal_four
- \fi}
+\def\syst_helpers_seventuple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_five
+ \else
+ \expandafter\syst_helpers_empty_normal_five
+ \fi}
- \def\syst_helpers_seventuple_empty_five_nop
- {\fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_three
- \else
- \expandafter\syst_helpers_empty_normal_three
- \fi}
+\def\syst_helpers_seventuple_empty_four_nop
+ {\fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_four
+ \else
+ \expandafter\syst_helpers_empty_normal_four
+ \fi}
- \def\syst_helpers_seventuple_empty_six_nop
- {\sixthargumentfalse
- \seventhargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_two
- \else
- \expandafter\syst_helpers_empty_normal_two
- \fi}
+\def\syst_helpers_seventuple_empty_five_nop
+ {\fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_three
+ \else
+ \expandafter\syst_helpers_empty_normal_three
+ \fi}
- \def\syst_helpers_seventuple_empty_seven_nop
- {\seventhargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_empty_spaced_one
- \else
- \expandafter\syst_helpers_empty_normal_one
- \fi}
+\def\syst_helpers_seventuple_empty_six_nop
+ {\sixthargumentfalse
+ \seventhargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_two
+ \else
+ \expandafter\syst_helpers_empty_normal_two
+ \fi}
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doseventupleempty#1%
- {%syst_helpers_argument_reset
- \t_syst_aux{#1}%
- \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop}
-
- \def\syst_helpers_seventuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop}
-
- \def\syst_helpers_seventuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop}
-
- \def\syst_helpers_seventuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop}
-
- \def\syst_helpers_seventuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop}
-
- \def\syst_helpers_seventuple_empty_five_yes[#1]%
- {\fifthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop}
-
- \def\syst_helpers_seventuple_empty_six_yes[#1]%
- {\sixthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop}
-
- \def\syst_helpers_seventuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][][][][]}
-
- \def\syst_helpers_seventuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][][][]}
-
- \def\syst_helpers_seventuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][][]}
-
- \def\syst_helpers_seventuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][]}
-
- \def\syst_helpers_seventuple_empty_five_nop
- {\fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][]}
-
- \def\syst_helpers_seventuple_empty_six_nop
- {\sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][]}
-
- \def\syst_helpers_seventuple_empty_seven_nop
- {\seventhargumentfalse
- \the\t_syst_aux[]}
-
-\stoplmtxmode
+\def\syst_helpers_seventuple_empty_seven_nop
+ {\seventhargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_empty_spaced_one
+ \else
+ \expandafter\syst_helpers_empty_normal_one
+ \fi}
%D Aliases:
@@ -3984,252 +3462,94 @@
%D \type {conditional} token. Okay, these macros are not called that often but it
%D saves crap when tracing.
-\startmkivmode
-
- \unexpanded\def\syst_helpers_get_grouped_argument#1#2%
- {\let\syst_helpers_get_grouped_argument_yes#1%
- \let\syst_helpers_get_grouped_argument_nop#2%
- \futurelet\nextargument\syst_helpers_get_grouped_argument_indeed}
+\unexpanded\def\syst_helpers_get_grouped_argument#1#2%
+ {\let\syst_helpers_get_grouped_argument_yes#1%
+ \let\syst_helpers_get_grouped_argument_nop#2%
+ \futurelet\nextargument\syst_helpers_get_grouped_argument_indeed}
- \def\syst_helpers_get_grouped_argument_indeed
- {\ifx\nextargument\bgroup
- \expandafter\syst_helpers_get_grouped_argument_a
- \else
- \expandafter\syst_helpers_get_grouped_argument_b
- \fi}
+\def\syst_helpers_get_grouped_argument_indeed
+ {\ifx\nextargument\bgroup
+ \expandafter\syst_helpers_get_grouped_argument_a
+ \else
+ \expandafter\syst_helpers_get_grouped_argument_b
+ \fi}
- \def\syst_helpers_get_grouped_argument_a
- {%syst_helpers_argument_reset
- \syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nested}
+\def\syst_helpers_get_grouped_argument_a
+ {%syst_helpers_argument_reset
+ \syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nested}
- \def\syst_helpers_get_grouped_argument_b
- {\ifconditional\c_syst_helpers_permit_spaces_between_groups
- \expandafter\syst_helpers_get_grouped_argument_f
- \else
- \expandafter\syst_helpers_get_grouped_argument_d
- \fi}
+\def\syst_helpers_get_grouped_argument_b
+ {\ifconditional\c_syst_helpers_permit_spaces_between_groups
+ \expandafter\syst_helpers_get_grouped_argument_f
+ \else
+ \expandafter\syst_helpers_get_grouped_argument_d
+ \fi}
- \def\syst_helpers_get_grouped_argument_d
- {%syst_helpers_argument_error
- \syst_helpers_get_grouped_argument_nop\syst_helpers_get_grouped_argument_nested{}}
+\def\syst_helpers_get_grouped_argument_d
+ {%syst_helpers_argument_error
+ \syst_helpers_get_grouped_argument_nop\syst_helpers_get_grouped_argument_nested{}}
- \begingroup
- \def\\ {\syst_helpers_get_grouped_argument\syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nop}
- \glet\syst_helpers_get_grouped_argument_e\\
- \endgroup
+\begingroup
+ \def\\ {\syst_helpers_get_grouped_argument\syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nop}
+ \glet\syst_helpers_get_grouped_argument_e\\
+\endgroup
- \def\syst_helpers_get_grouped_argument_f
- {\ifx\nextargument\blankspace
- \expandafter\syst_helpers_get_grouped_argument_e % g
- \else
- \expandafter\syst_helpers_get_grouped_argument_d % h
- \fi}
+\def\syst_helpers_get_grouped_argument_f
+ {\ifx\nextargument\blankspace
+ \expandafter\syst_helpers_get_grouped_argument_e % g
+ \else
+ \expandafter\syst_helpers_get_grouped_argument_d % h
+ \fi}
- \unexpanded\def\dosinglegroupempty#1%
- {\def\syst_helpers_get_grouped_argument_nested
- {\dontpermitspacesbetweengroups
- #1}%
- \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
-
- \unexpanded\def\dodoublegroupempty#1%
- {\def\syst_helpers_get_grouped_argument_nested##1%
- {\def\syst_helpers_get_grouped_argument_nested
- {\dontpermitspacesbetweengroups
- #1{##1}}%
- \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
- \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
-
- \unexpanded\def\dotriplegroupempty#1%
- {\def\syst_helpers_get_grouped_argument_nested##1%
- {\def\syst_helpers_get_grouped_argument_nested####1%
- {\def\syst_helpers_get_grouped_argument_nested
- {\dontpermitspacesbetweengroups
- #1{##1}{####1}}%
- \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
- \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
- \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
-
- \unexpanded\def\doquadruplegroupempty#1%
- {\def\syst_helpers_get_grouped_argument_nested##1%
- {\def\syst_helpers_get_grouped_argument_nested####1%
- {\def\syst_helpers_get_grouped_argument_nested########1%
- {\def\syst_helpers_get_grouped_argument_nested
- {\dontpermitspacesbetweengroups
- #1{##1}{####1}{########1}}%
- \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
- \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
- \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
- \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
-
- \unexpanded\def\doquintuplegroupempty#1%
- {\def\syst_helpers_get_grouped_argument_nested##1%
- {\def\syst_helpers_get_grouped_argument_nested####1%
- {\def\syst_helpers_get_grouped_argument_nested########1%
- {\def\syst_helpers_get_grouped_argument_nested################1%
- {\def\syst_helpers_get_grouped_argument_nested
- {\dontpermitspacesbetweengroups
- #1{##1}{####1}{########1}{################1}}%
- \syst_helpers_get_grouped_argument\fifthargumenttrue\fifthargumentfalse}%
- \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
- \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
- \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
- \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\dosinglegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop}
-
- \def\syst_helpers_single_group_empty_one_nop
- {\firstargumentfalse
- \the\t_syst_aux{}}
-
- \unexpanded\def\dodoublegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop}
-
- \def\syst_helpers_group_double_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop}
-
- \def\syst_helpers_group_double_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \the\t_syst_aux{}{}}
-
- \def\syst_helpers_group_double_empty_two_nop
- {\secondargumentfalse
- \the\t_syst_aux{}}
-
- \unexpanded\def\dotriplegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop}
-
- \def\syst_helpers_group_triple_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop}
-
- \def\syst_helpers_group_triple_empty_two_yes#1%
- {\secondargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop}
-
- \def\syst_helpers_group_triple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux{}{}{}}
-
- \def\syst_helpers_group_triple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux{}{}}
-
- \def\syst_helpers_group_triple_empty_three_nop
- {\thirdargumentfalse
- \the\t_syst_aux{}}
-
- \unexpanded\def\doquadruplegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop}
-
- \def\syst_helpers_group_quadruple_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop}
-
- \def\syst_helpers_group_quadruple_empty_two_yes#1%
- {\secondargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop}
-
- \def\syst_helpers_group_quadruple_empty_three_yes#1%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop}
-
- \def\syst_helpers_group_quadruple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux{}{}{}{}}
-
- \def\syst_helpers_group_quadruple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux{}{}{}}
-
- \def\syst_helpers_group_quadruple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux{}{}}
-
- \def\syst_helpers_group_quadruple_empty_four_nop
- {\fourthargumentfalse
- \the\t_syst_aux{}}
-
- \unexpanded\def\doquintuplegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop}
-
- \def\syst_helpers_group_quintuple_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop}
-
- \def\syst_helpers_group_quintuple_empty_two_yes#1%
- {\secondargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop}
-
- \def\syst_helpers_group_quintuple_empty_three_yes#1%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop}
-
- \def\syst_helpers_group_quintuple_empty_four_yes#1%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop}
-
- \def\syst_helpers_group_quintuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}{}{}{}}
-
- \def\syst_helpers_group_quintuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}{}{}}
-
- \def\syst_helpers_group_quintuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}{}}
-
- \def\syst_helpers_group_quintuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}}
-
- \def\syst_helpers_group_quintuple_empty_five_nop
- {\fifthargumentfalse
- \the\t_syst_aux{}}
-
-\stoplmtxmode
+\unexpanded\def\dosinglegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\unexpanded\def\dodoublegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\unexpanded\def\dotriplegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}{####1}}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\unexpanded\def\doquadruplegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested########1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}{####1}{########1}}%
+ \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\unexpanded\def\doquintuplegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested########1%
+ {\def\syst_helpers_get_grouped_argument_nested################1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}{####1}{########1}{################1}}%
+ \syst_helpers_get_grouped_argument\fifthargumenttrue\fifthargumentfalse}%
+ \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
%D These macros can explictly take care of spaces, which means that the next
%D definition and calls are valid:
@@ -5918,71 +5238,34 @@
% \unexpanded\def\pickupgroupedcommand#1#2#3%
% {\doifelsenextbgroup{\syst_helpers_handle_group_pickup{#1}{#2}{#3}}{\syst_helpers_handle_group_nop{#1}{#2}}}
-\startmkivmode
-
- \unexpanded\def\groupedcommand#1#2%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \def\m_syst_helpers_handle_group_a{#2}%
- \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
-
- \unexpanded\def\groupedcommandcs#1#2%
- {\let\m_syst_helpers_handle_group_b#1%
- \let\m_syst_helpers_handle_group_a#2%
- \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
-
- \unexpanded\def\simplegroupedcommand#1#2%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \def\m_syst_helpers_handle_group_a{#2}%
- \doifelsenextbgroupcs\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop}
-
- \unexpanded\def\pickupgroupedcommand#1#2#3%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \def\m_syst_helpers_handle_group_a{#2}%
- \def\m_syst_helpers_handle_group_p{#2}%
- \doifelsenextbgroupcs\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop}
-
- \unexpanded\def\triggergroupedcommand#1%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
+\unexpanded\def\groupedcommand#1#2%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
- \unexpanded\def\triggergroupedcommandcs#1%
- {\let\m_syst_helpers_handle_group_b#1%
- \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
+\unexpanded\def\groupedcommandcs#1#2%
+ {\let\m_syst_helpers_handle_group_b#1%
+ \let\m_syst_helpers_handle_group_a#2%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
-\stopmkivmode
+\unexpanded\def\simplegroupedcommand#1#2%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop}
-\startlmtxmode
+\unexpanded\def\pickupgroupedcommand#1#2#3%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \def\m_syst_helpers_handle_group_p{#2}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop}
- \unexpanded\def\groupedcommand#1#2%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \def\m_syst_helpers_handle_group_a{#2}%
- \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
+\unexpanded\def\triggergroupedcommand#1%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
- \unexpanded\def\groupedcommandcs#1#2%
- {\let\m_syst_helpers_handle_group_b#1%
- \let\m_syst_helpers_handle_group_a#2%
- \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
-
- \unexpanded\def\simplegroupedcommand#1#2%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \def\m_syst_helpers_handle_group_a{#2}%
- \futureexpandis\bgroup\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop}
-
- \unexpanded\def\pickupgroupedcommand#1#2#3%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \def\m_syst_helpers_handle_group_a{#2}%
- \def\m_syst_helpers_handle_group_p{#2}%
- \futureexpandis\bgroup\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop}
-
- \unexpanded\def\triggergroupedcommand#1%
- {\def\m_syst_helpers_handle_group_b{#1}%
- \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
-
- \unexpanded\def\triggergroupedcommandcs#1%
- {\let\m_syst_helpers_handle_group_b#1%
- \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
-
-\stoplmtxmode
+\unexpanded\def\triggergroupedcommandcs#1%
+ {\let\m_syst_helpers_handle_group_b#1%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
%D Users should be aware of the fact that grouping can interfere with ones paragraph
%D settings that are executed after the paragraph is closed. One should therefore
@@ -7032,166 +6315,88 @@
%D three tokens per call. Anyone familiar with the not||values ones, can derive
%D their meaning from the definitions.
-\startmkivmode
-
- \unexpanded\def\doifvalue#1#2%
- {\edef\m_syst_string_one{\csname#1\endcsname}%
- \edef\m_syst_string_two{#2}%
- \ifx\m_syst_string_one\m_syst_string_two
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
-
- \unexpanded\def\doifnotvalue#1#2%
- {\edef\m_syst_string_one{\csname#1\endcsname}%
- \edef\m_syst_string_two{#2}%
- \ifx\m_syst_string_one\m_syst_string_two
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
-
- \unexpanded\def\doifelsevalue#1#2%
- {\edef\m_syst_string_one{\csname#1\endcsname}%
- \edef\m_syst_string_two{#2}%
- \ifx\m_syst_string_one\m_syst_string_two
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
- \unexpanded\def\doifnothing#1%
- {\edef\m_syst_string_one{#1}%
- \ifx\m_syst_string_one\empty
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
-
- \unexpanded\def\doifsomething#1%
- {\edef\m_syst_string_one{#1}%
- \ifx\m_syst_string_one\empty
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
-
- \unexpanded\def\doifelsenothing#1%
- {\edef\m_syst_string_one{#1}%
- \ifx\m_syst_string_one\empty
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
- \unexpanded\def\doifelsesomething#1%
- {\edef\m_syst_string_one{#1}%
- \ifx\m_syst_string_one\empty
- \expandafter\secondoftwoarguments
- \else
- \expandafter\firstoftwoarguments
- \fi}
-
- \unexpanded\def\doifvaluenothing#1%
- {\edef\m_syst_string_one{\csname#1\endcsname}%
- \ifx\m_syst_string_one\empty
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
-
- \unexpanded\def\doifvaluesomething#1%
- {\edef\m_syst_string_one{\csname#1\endcsname}%
- \ifx\m_syst_string_one\empty
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
-
- \unexpanded\def\doifelsevaluenothing#1%
- {\edef\m_syst_string_one{\csname#1\endcsname}%
- \ifx\m_syst_string_one\empty
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifvalue#1#2%
- {\iftok{\csname#1\endcsname}{#2}%
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
-
- \unexpanded\def\doifnotvalue#1#2%
- {\iftok{\csname#1\endcsname}{#2}%
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
+\unexpanded\def\doifvalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
- \unexpanded\def\doifelsevalue#1#2%
- {\iftok{\csname#1\endcsname}{#2}%
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
+\unexpanded\def\doifnotvalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
- \unexpanded\def\doifnothing#1%
- {\iftok{#1}\emptytoks
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
+\unexpanded\def\doifelsevalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
- \unexpanded\def\doifsomething#1%
- {\iftok{#1}\emptytoks
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
+\unexpanded\def\doifnothing#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
- \unexpanded\def\doifelsenothing#1%
- {\iftok{#1}\emptytoks
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
+\unexpanded\def\doifsomething#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
- \unexpanded\def\doifelsesomething#1%
- {\iftok{#1}\emptytoks
- \expandafter\secondoftwoarguments
- \else
- \expandafter\firstoftwoarguments
- \fi}
+\unexpanded\def\doifelsenothing#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
- \unexpanded\def\doifvaluenothing#1%
- {\iftok{\csname#1\endcsname}\emptytoks
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
+\unexpanded\def\doifelsesomething#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
- \unexpanded\def\doifvaluesomething#1%
- {\iftok{\csname#1\endcsname}\emptytoks
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
+\unexpanded\def\doifvaluenothing#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
- \unexpanded\def\doifelsevaluenothing#1%
- {\iftok{\csname#1\endcsname}\emptytoks
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
+\unexpanded\def\doifvaluesomething#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
-\stoplmtxmode
+\unexpanded\def\doifelsevaluenothing#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
\let\doifvalueelse \doifelsevalue
\let\doifnothingelse \doifelsenothing
@@ -7970,58 +7175,29 @@
%D
%D Not that fast I guess, but here's a way to test for token registers being empty.
-\startmkivmode
-
- \unexpanded\def\doifelsesometoks#1%
- {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
- \ifx\m_syst_string_one\empty
- \expandafter\secondoftwoarguments
- \else
- \expandafter\firstoftwoarguments
- \fi}
-
- \unexpanded\def\doifsometoks#1%
- {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
- \ifx\m_syst_string_one\empty
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
-
- \unexpanded\def\doifemptytoks#1%
- {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
- \ifx\m_syst_string_one\empty
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
-
-\stopmkivmode
-
-\startlmtxmode
-
- \unexpanded\def\doifelsesometoks#1%
- {\iftok#1\emptytoks
- \expandafter\secondoftwoarguments
- \else
- \expandafter\firstoftwoarguments
- \fi}
-
- \unexpanded\def\doifsometoks#1%
- {\iftok#1\emptytoks
- \expandafter\gobbleoneargument
- \else
- \expandafter\firstofoneargument
- \fi}
+\unexpanded\def\doifelsesometoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
- \unexpanded\def\doifemptytoks#1%
- {\iftok#1\emptytoks
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
+\unexpanded\def\doifsometoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
-\stoplmtxmode
+\unexpanded\def\doifemptytoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
\let\doifsometokselse\doifelsesometoks
@@ -8234,33 +7410,18 @@
%D
%D This is a dirty one: we simply append a unit and discard it when needed.
-\startmkivmode
-
- \def\doifelsedimension#1%
- {\afterassignment\syst_helpers_if_dimension_else\privatescratchdimen#1pt\relax}
-
- % \def\doifelsedimension#1%
- % {\expandafter\syst_helpers_if_dimension_else\immediateassignment\privatescratchdimen#1pt\relax}
-
- \def\syst_helpers_if_dimension_else#1%
- {\ifx#1\relax
- \expandafter\secondoftwoarguments
- \else % #1=p ... t\relax
- \expandafter\thirdoffourarguments
- \fi}
-
-\stopmkivmode
+\def\doifelsedimension#1%
+ {\afterassignment\syst_helpers_if_dimension_else\privatescratchdimen#1pt\relax}
-\startlmtxmode
+% \def\doifelsedimension#1%
+% {\expandafter\syst_helpers_if_dimension_else\immediateassignment\privatescratchdimen#1pt\relax}
- \def\doifelsedimension#1%
- {\ifchkdim#1\or
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
-\stoplmtxmode
+\def\syst_helpers_if_dimension_else#1%
+ {\ifx#1\relax
+ \expandafter\secondoftwoarguments
+ \else % #1=p ... t\relax
+ \expandafter\thirdoffourarguments
+ \fi}
\let\doifdimensionelse\doifelsedimension
@@ -8281,67 +7442,57 @@
%D \NC 1 \NC \doifdimenstringelse {1}{yes}{no} \NC \NR
%D \stoptabulate
-\startmkivmode
-
- \installsystemnamespace{dimenchecka}
- \installsystemnamespace{dimencheckb}
- \installsystemnamespace{dimencheckc}
-
- \def\doifelsedimenstring#1{\normalexpanded{\noexpand\dodimenteststageone#1}\empty\empty]}
-
- \def\dodimenteststageone #1#2{\csname \??dimenchecka\ifcsname \??dimenchecka#2\endcsname#2\else x\fi\endcsname#2}
- \def\dodimenteststagetwo #1#2{\csname \??dimencheckb\ifcsname \??dimencheckb#2\endcsname#2\else x\fi\endcsname#2}
- \def\dodimenteststagethree #1]{\csname \??dimencheckc\ifcsname \??dimencheckc#1\endcsname#1\else x\fi\endcsname}
-
- \expandafter\let\csname \??dimenchecka x\endcsname\dodimenteststagethree
- \expandafter\let\csname \??dimencheckb x\endcsname\dodimenteststagethree
- \expandafter\let\csname \??dimencheckc x\endcsname\secondoftwoarguments
-
- \expandafter\let\csname \??dimenchecka.\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimenchecka,\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimenchecka1\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka2\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka3\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka4\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka5\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka6\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka7\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka8\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka9\endcsname\dodimenteststageone
- \expandafter\let\csname \??dimenchecka0\endcsname\dodimenteststageone
-
- \expandafter\let\csname \??dimencheckb1\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb2\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb3\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb4\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb5\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb6\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb7\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb8\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb9\endcsname\dodimenteststagetwo
- \expandafter\let\csname \??dimencheckb0\endcsname\dodimenteststagetwo
-
- \expandafter\let\csname \??dimencheckc pt\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc pc\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc in\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc bp\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc cm\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc mm\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc dd\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc cc\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc sp\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc ex\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc em\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc nd\endcsname\firstoftwoarguments
- \expandafter\let\csname \??dimencheckc nc\endcsname\firstoftwoarguments
-
-\stopmkivmode
-
-\startlmtxmode
-
- \let\doifelsedimenstring\doifelsedimension
-
-\stoplmtxmode
+\installsystemnamespace{dimenchecka}
+\installsystemnamespace{dimencheckb}
+\installsystemnamespace{dimencheckc}
+
+\def\doifelsedimenstring#1{\normalexpanded{\noexpand\dodimenteststageone#1}\empty\empty]}
+
+\def\dodimenteststageone #1#2{\csname \??dimenchecka\ifcsname \??dimenchecka#2\endcsname#2\else x\fi\endcsname#2}
+\def\dodimenteststagetwo #1#2{\csname \??dimencheckb\ifcsname \??dimencheckb#2\endcsname#2\else x\fi\endcsname#2}
+\def\dodimenteststagethree #1]{\csname \??dimencheckc\ifcsname \??dimencheckc#1\endcsname#1\else x\fi\endcsname}
+
+\expandafter\let\csname \??dimenchecka x\endcsname\dodimenteststagethree
+\expandafter\let\csname \??dimencheckb x\endcsname\dodimenteststagethree
+\expandafter\let\csname \??dimencheckc x\endcsname\secondoftwoarguments
+
+\expandafter\let\csname \??dimenchecka.\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimenchecka,\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimenchecka1\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka2\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka3\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka4\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka5\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka6\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka7\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka8\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka9\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka0\endcsname\dodimenteststageone
+
+\expandafter\let\csname \??dimencheckb1\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb2\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb3\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb4\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb5\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb6\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb7\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb8\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb9\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb0\endcsname\dodimenteststagetwo
+
+\expandafter\let\csname \??dimencheckc pt\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc pc\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc in\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc bp\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc cm\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc mm\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc dd\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc cc\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc sp\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc ex\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc em\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc nd\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc nc\endcsname\firstoftwoarguments
\let\doifdimenstringelse\doifelsedimenstring
diff --git a/tex/context/base/mkiv/syst-aux.mkxl b/tex/context/base/mkiv/syst-aux.mkxl
new file mode 100644
index 000000000..725deb866
--- /dev/null
+++ b/tex/context/base/mkiv/syst-aux.mkxl
@@ -0,0 +1,6558 @@
+%D \module
+%D [ file=syst-aux, % merge of syst-gen cum suis
+%D version=1996.03.20,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=General,
+%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.
+
+\registerctxluafile{syst-aux}{}
+
+%D This fils is a follow up in \type {syst-aux.mkii} and \type {syst-aux.mkiv}
+%D where you can find some more pure \TEX\ or \LUATEX| variants.
+
+\unprotect
+
+%D \macros
+%D {unexpanded}
+%D
+%D Because we use this module only in \MKIV, we have removed the old protection
+%D code.
+%D
+%D \starttyping
+%D \unexpanded\def\somecommand{... ... ...}
+%D \stoptyping
+%D
+%D This overloads the \ETEX\ primitive but as we already had an \MKII\ solution we
+%D keep the same name for a similar mechanism.
+
+\let\unexpanded\normalprotected
+
+\ifcase\contextlmtxmode
+
+ \def\startlmtxmode#1\stoplmtxmode{}
+ \let\stoplmtxmode \relax
+ \let\startmkivmode\relax
+ \let\stopmkivmode \relax
+
+\else
+
+ \let\startlmtxmode\relax
+ \let\stoplmtxmode \relax
+ \def\startmkivmode#1\stopmkivmode{}
+ \let\stopmkivmode \relax
+
+\fi
+
+%D As we don't have namespace definers yet, we use a special one:
+
+\ifdefined\c_syst_helpers_n_of_namespaces
+
+ % lets plug in a better error message
+
+\else
+
+ \newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes
+
+ \def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>}
+ %def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet
+
+\fi
+
+\unexpanded\def\installsystemnamespace#1% maybe move this to syst-ini
+ {\ifcsname ??#1\endcsname
+ \writestatus\m!system{duplicate system namespace '#1'}\wait
+ \else
+ \global\advance\c_syst_helpers_n_of_namespaces\plusone
+ \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}%
+ \fi}
+
+%D \macros
+%D {normalspace}
+%D
+%D There is already \type{\space} but just to be sure we also provide:
+
+\def\normalspace{ }
+
+%D \macros
+%D {!!count, !!toks, !!dimen, !!box,
+%D !!width, !!height, !!depth, !!string, !!done}
+%D
+%D We define some more \COUNTERS\ and \DIMENSIONS. We also define some shortcuts to
+%D the local scatchregisters~0, 2, 4, 6 and~8.
+
+\newcount\!!counta \newtoks\!!toksa \newdimen\!!dimena \newbox\!!boxa
+\newcount\!!countb \newtoks\!!toksb \newdimen\!!dimenb \newbox\!!boxb
+\newcount\!!countc \newtoks\!!toksc \newdimen\!!dimenc \newbox\!!boxc
+\newcount\!!countd \newtoks\!!toksd \newdimen\!!dimend \newbox\!!boxd
+\newcount\!!counte \newtoks\!!tokse \newdimen\!!dimene \newbox\!!boxe
+\newcount\!!countf \newtoks\!!toksf \newdimen\!!dimenf \newbox\!!boxf
+ \newdimen\!!dimeng
+ \newdimen\!!dimenh
+ \newdimen\!!dimeni
+ \newdimen\!!dimenj
+ \newdimen\!!dimenk
+
+\let\!!stringa\empty \let\!!stringb\empty \let\!!stringc\empty
+\let\!!stringd\empty \let\!!stringe\empty \let\!!stringf\empty
+
+\newdimen\!!widtha \newdimen\!!heighta \newdimen\!!deptha
+\newdimen\!!widthb \newdimen\!!heightb \newdimen\!!depthb
+\newdimen\!!widthc \newdimen\!!heightc \newdimen\!!depthc
+\newdimen\!!widthd \newdimen\!!heightd \newdimen\!!depthd
+
+\newif\if!!donea \newif\if!!doneb \newif\if!!donec
+\newif\if!!doned \newif\if!!donee \newif\if!!donef
+
+\def\!!zerocount {0} % alongside \zerocount
+\def\!!minusone {-1} % ...
+\def\!!plusone {1} % ...
+\def\!!plustwo {2} % ...
+\def\!!plusthree {3} % ...
+\def\!!plusfour {4} % ...
+\def\!!plusfive {5} % ...
+\def\!!plussix {6} % ...
+\def\!!plusseven {7} % ...
+\def\!!pluseight {8} % ...
+\def\!!plusnine {9} % alongside \plusnine
+
+\setnewconstant \uprotationangle 0
+\setnewconstant\rightrotationangle 90
+\setnewconstant \downrotationangle 180
+\setnewconstant \leftrotationangle 270
+
+\ifdefined\data \else \let\data \relax \fi % dep checker
+
+%D \macros
+%D {s!,c!,e!,p!,v!,@@,??}
+%D
+%D To save memory, we use constants (sometimes called variables). Redefining these
+%D constants can have disastrous results.
+
+\def\v!prefix! {v!}
+\def\c!prefix! {c!}
+\def\s!prefix! {s!}
+
+\def\s!next {next}
+\def\s!default {default}
+\def\s!dummy {dummy}
+\def\s!unknown {unknown}
+
+\def\s!do {do}
+\def\s!dodo {dodo}
+
+\def\s!complex {complex}
+\def\s!start {start}
+\def\s!simple {simple}
+\def\s!stop {stop}
+
+\def\s!empty {empty}
+
+%D Sometimes we pass macros as arguments to commands that don't expand them
+%D before interpretation. Such commands can be enclosed with \type {\expanded},
+%D like:
+%D
+%D \starttyping
+%D \expanded{\setupsomething[\alfa]}
+%D \stoptyping
+%D
+%D Such situations occur for instance when \type{\alfa} is a commalist or when data
+%D stored in macros is fed to index of list commands. If needed, one should use
+%D \type{\noexpand} inside the argument. Later on we will meet some more clever
+%D alternatives to this command. Beware, only the simple one has \type {\noexpand}
+%D before its argument.
+
+\let\m_syst_helpers_expanded\empty
+
+\unexpanded\def\expanded#1%
+ {\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded}
+
+\unexpanded\def\startexpanded#1\stopexpanded
+ {\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded}
+
+\let\stopexpanded\relax
+
+%D Recent \TEX\ engines have a primitive \type {\expanded} and we will use that when
+%D possible. After all, we can make not expandable macros now.
+
+% We cannot use the next variant as first we need to adapt \type {##}'s in callers:
+%
+% \def\expanded#1%
+% {\normalexpanded{\noexpand#1}}
+%
+% \def\startexpanded#1\stopexpanded
+% {\normalexpanded{#1}}
+
+%D \macros
+%D {gobbleoneargument,gobble...arguments}
+%D
+%D The next set of macros just do nothing, except that they get rid of a number of
+%D arguments.
+
+\def\gobbleoneargument #1{}
+\def\gobbletwoarguments #1#2{}
+\def\gobblethreearguments#1#2#3{}
+\def\gobblefourarguments #1#2#3#4{}
+\def\gobblefivearguments #1#2#3#4#5{}
+\def\gobblesixarguments #1#2#3#4#5#6{}
+\def\gobblesevenarguments#1#2#3#4#5#6#7{}
+\def\gobbleeightarguments#1#2#3#4#5#6#7#8{}
+\def\gobbleninearguments #1#2#3#4#5#6#7#8#9{}
+\def\gobbletenarguments #1{\gobbleninearguments}
+
+\def\gobbleoneoptional [#1]{}
+\def\gobbletwooptionals [#1][#2]{}
+\def\gobblethreeoptionals[#1][#2][#3]{}
+\def\gobblefouroptionals [#1][#2][#3][#4]{}
+\def\gobblefiveoptionals [#1][#2][#3][#4][#5]{}
+
+%D Reserved macros for tests:
+
+\let\donothing\empty
+
+\let\m_syst_string_one \empty
+\let\m_syst_string_two \empty
+\let\m_syst_string_three\empty
+\let\m_syst_string_four \empty
+
+\let\m_syst_action_yes \empty
+\let\m_syst_action_nop \empty
+
+%D \macros
+%D {doifnextcharelse}
+%D
+%D When we started using \TEX\ in the late eighties, our first experiences with
+%D programming concerned a simple shell around \LATEX. The commands probably use
+%D most at \PRAGMA, are the itemizing ones. One of those few shell commands took
+%D care of an optional argument, that enabled us to specify what kind of item symbol
+%D we wanted. Without understanding anything we were able to locate a \LATEX\ macro
+%D that could be used to inspect the next character.
+%D
+%D It's this macro that the ancester of the next one presented here. It executes one
+%D of two actions, dependant of the next character. Disturbing spaces and line
+%D endings, which are normally interpreted as spaces too, are skipped.
+%D
+%D \starttyping
+%D \doifnextcharelse {karakter} {then ...} {else ...}
+%D \stoptyping
+%D
+%D This macro differs from the original in the use of \type {\localnext} because we
+%D don't want clashes with \type {\next}.
+
+\let\next \relax
+\let\nextnext \relax
+\let\nextnextnext \relax
+\let\nexttoken \relax
+\let\charactertoken\relax
+
+\let\m_syst_action_yes\relax
+\let\m_syst_action_nop\relax
+
+% \def\syst_helpers_inspect_next_character
+% {\ifx\nexttoken\blankspace
+% \expandafter\syst_helpers_reinspect_next_character
+% \else
+% \expandafter\syst_helpers_inspect_next_character_indeed
+% \fi}
+%
+% \def\syst_helpers_inspect_next_character_indeed
+% {\ifx\nexttoken\charactertoken
+% \expandafter\m_syst_action_yes
+% \else
+% \expandafter\m_syst_action_nop
+% \fi}
+
+\unexpanded\def\doifelsenextchar#1#2#3% #1 should not be {} !
+ {\def\m_syst_action_yes{#2}%
+ \def\m_syst_action_nop{#3}%
+ \futureexpandis#1\m_syst_action_yes\m_syst_action_nop}
+
+\unexpanded\def\doifelsenextcharcs % #1#2#3% #1 should not be {} !
+ {\futureexpandis}
+
+\let\doifnextcharelse \doifelsenextchar
+\let\doifnextcharcselse\doifelsenextcharcs
+
+%D Because we will mostly use this macro for testing if the next character is \type
+%D {[}, we also make a slightly faster variant as it is not uncommon to have tens of
+%D thousands of calls to this test in a run. Of course it also is more convenient to
+%D read a trace then.
+
+% \newif\if_next_blank_space_token
+
+% \let\syst_helpers_next_optional_character_token=[
+%
+% \def\syst_helpers_inspect_next_optional_character
+% {\ifx\nexttoken\blankspace
+% \expandafter\syst_helpers_reinspect_next_optional_character
+% \else
+% \expandafter\syst_helpers_inspect_next_optional_character_indeed
+% \fi}
+%
+% \def\syst_helpers_inspect_next_optional_character_indeed
+% {\ifx\nexttoken\syst_helpers_next_optional_character_token
+% \expandafter\m_syst_action_yes
+% \else
+% \expandafter\m_syst_action_nop
+% \fi}
+
+\unexpanded\def\doifelsenextoptional#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \futureexpandis[\m_syst_action_yes\m_syst_action_nop}
+
+\unexpanded\def\doifelsenextoptionalcs
+ {\futureexpandis[}
+
+\let\doifnextoptionalelse \doifelsenextoptional
+\let\doifnextoptionalcselse\doifelsenextoptionalcs
+
+% \let\syst_helpers_next_bgroup_character_token\bgroup
+%
+% \def\syst_helpers_inspect_next_bgroup_character
+% {\ifx\nexttoken\blankspace
+% \expandafter\syst_helpers_reinspect_next_bgroup_character
+% \else
+% \expandafter\syst_helpers_inspect_next_bgroup_character_indeed
+% \fi}
+%
+% \def\syst_helpers_inspect_next_bgroup_character_indeed
+% {\ifx\nexttoken\syst_helpers_next_bgroup_character_token
+% \expandafter\m_syst_action_yes
+% \else
+% \expandafter\m_syst_action_nop
+% \fi}
+
+\unexpanded\def\doifelsenextbgroup#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \futureexpandis\bgroup\m_syst_action_yes\m_syst_action_nop}
+
+\unexpanded\def\doifelsenextbgroupcs % #1#2
+ {\futureexpandis\bgroup}
+
+\let\doifnextbgroupelse \doifelsenextbgroup
+\let\doifnextbgroupcselse\doifelsenextbgroupcs
+
+% \let\syst_helpers_next_parenthesis_character_token(
+%
+% \def\syst_helpers_inspect_next_parenthesis_character
+% {\ifx\nexttoken\blankspace
+% \expandafter\syst_helpers_reinspect_next_parenthesis_character
+% \else
+% \expandafter\syst_helpers_inspect_next_parenthesis_character_indeed
+% \fi}
+%
+% \def\syst_helpers_inspect_next_parenthesis_character_indeed
+% {\ifx\nexttoken\syst_helpers_next_parenthesis_character_token
+% \expandafter\m_syst_action_yes
+% \else
+% \expandafter\m_syst_action_nop
+% \fi}
+
+\unexpanded\def\doifelsenextparenthesis#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \futureexpandis(\m_syst_action_yes\m_syst_action_nop}
+
+\let\doifnextparenthesiselse\doifelsenextparenthesis
+
+%D The next one is handy in predictable situations:
+
+\def\syst_helpers_do_if_fast_optional_check_else
+ {\ifx\nexttoken\syst_helpers_next_optional_character_token
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+\unexpanded\def\doifelsefastoptionalcheck#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \futureexpandis[\m_syst_action_yes\m_syst_action_nop}
+
+\unexpanded\def\doifelsefastoptionalcheckcs
+ {\futureexpandis[}
+
+\let\doiffastoptionalcheckelse \doifelsefastoptionalcheck
+\let\doiffastoptionalcheckcselse\doifelsefastoptionalcheckcs
+
+%D Here's one for skipping spaces and pars, handy for:
+%D
+%D \starttyping
+%D \hbox
+%D
+%D {a few lines later}
+%D \stoptyping
+%D
+%D like:
+%D
+%D \starttyping
+%D \def\somecommand{\dowithnextbox{\box\nextbox}\ruledhbox}
+%D
+%D \assumelongusagecs\somecommand
+%D
+%D \bgroup
+%D oeps
+%D \egroup
+%D \stoptyping
+
+%D The cumbersome original:
+
+% \unexpanded\def\assumelongusagecs#1%
+% {\let\m_syst_action#1%
+% \futurelet\nexttoken\syst_helpers_ignore_spacing}
+%
+% \def\syst_helpers_ignore_spacing
+% {\ifx\nexttoken\blankspace
+% \expandafter\syst_helpers_ignore_spacing_blankspace
+% \orelse\ifx\nexttoken\par
+% \expandafter\syst_helpers_ignore_spacing_partoken
+% \else
+% \expandafter\m_syst_action
+% \fi}
+%
+% \def\syst_helpers_ignore_spacing_partoken\par
+% {\futurelet\nexttoken\syst_helpers_ignore_spacing}
+
+%D A bit less tracing noise:
+
+% \def\assume_long_usage_cs
+% {\futureexpandis\par\assume_long_usage_par\m_syst_action}
+%
+% \def\assume_long_usage_par\par%
+% {\assume_long_usage_cs}
+%
+% \unexpanded\def\assumelongusagecs#1{\let\m_syst_action#1\assume_long_usage_cs}
+
+%D Ok, using \type {\futureexpandisap} is maybe feature creep but I'd like to experiment
+%D with more tolerant user input. It might go away in which case we use the above.
+
+\unexpanded\def\assumelongusagecs#1%
+ {\futureexpandisap\relax#1#1}
+
+% D These macros use some auxiliary macros. Although we were able to program quite
+% D complicated things, I only understood these after rereading the \TEX book. The
+% D trick is in using a command with a one character name. Such commands differ from
+% D the longer ones in the fact that trailing spaces are {\em not} skipped. This
+% D enables us to indirectly define a long named macro that gobbles a space. In the
+% D first line we define \type {\blankspace}. Next we make \type {\:} equivalent to
+% D \type {\reinspect...}. This one||character command is expanded before the next
+% D \type {\def} comes into action. This way the space after \type {\:} becomes a
+% D delimiter of the longer named \type {\reinspectnextcharacter}.
+
+\let\next\:
+
+\def\:{\let\blankspace= } \:
+
+% \def\:{\syst_helpers_reinspect_next_character}
+% \expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_character}
+%
+% \def\:{\syst_helpers_reinspect_next_optional_character}
+% \expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+%
+% \def\:{\syst_helpers_reinspect_next_bgroup_character}
+% \expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
+%
+% \def\:{\syst_helpers_reinspect_next_parenthesis_character}
+% \expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
+%
+% \def\:{\syst_helpers_ignore_spacing_blankspace}
+% \expandafter\def\: {\futurelet\nexttoken\syst_helpers_ignore_spacing}
+
+\let\:\next
+
+%D \macros
+%D {setvalue,setgvalue,setevalue,setxvalue,
+%D letvalue,letgvalue,getvalue,resetvalue,
+%D undefinevalue,ignorevalue}
+%D
+%D \TEX's primitive \type {\csname} can be used to construct all kind of commands
+%D that cannot be defined with \type {\def} and \type {\let}. Every macro programmer
+%D sooner or later wants macros like these.
+%D
+%D \starttyping
+%D \setvalue {name}{...} = \def\name{...}
+%D \setgvalue {name}{...} = \gdef\name{...}
+%D \setevalue {name}{...} = \edef\name{...}
+%D \setxvalue {name}{...} = \xdef\name{...}
+%D \letvalue {name}=\... = \let\name=\...
+%D \letgvalue {name}=\... = \glet\name=\...
+%D \getvalue {name} = \name
+%D \resetvalue {name} = \def\name{}
+%D \stoptyping
+%D
+%D As we will see, \CONTEXT\ uses these commands many times, which is mainly due to
+%D its object oriented and parameter driven character.
+
+\def\setvalue #1{\expandafter\def \csname#1\endcsname}
+\def\setgvalue #1{\expandafter\gdef\csname#1\endcsname}
+\def\setevalue #1{\expandafter\edef\csname#1\endcsname}
+\def\setxvalue #1{\expandafter\xdef\csname#1\endcsname}
+\def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname
+\def\letvalue #1{\expandafter\let \csname#1\endcsname}
+\def\letgvalue #1{\expandafter\glet\csname#1\endcsname}
+\def\resetvalue #1{\expandafter\let \csname#1\endcsname\empty}
+\def\undefinevalue#1{\expandafter\let \csname#1\endcsname\undefined}
+\def\ignorevalue#1#2{\expandafter\let \csname#1\endcsname\empty}
+
+\def\setuvalue #1{\normalprotected\expandafter \def\csname#1\endcsname}
+\def\setuevalue #1{\normalprotected\expandafter\edef\csname#1\endcsname}
+\def\setugvalue #1{\normalprotected\expandafter\gdef\csname#1\endcsname}
+\def\setuxvalue #1{\normalprotected\expandafter\xdef\csname#1\endcsname}
+
+\unexpanded\def\getuvalue#1{\csname#1\endcsname}
+
+%D \macros
+%D {globallet,glet}
+%D
+%D In \CONTEXT\ of May 2000 using \type {\globallet} instead of the two tokens will
+%D save us some $300\times4=1200$ bytes of format file on a 32~bit system. Not that
+%D it matters much today. This shortcut is already defined:
+
+\let\globallet\glet
+
+%D \macros
+%D {doifundefined,doifdefined,
+%D doifundefinedelse,doifdefinedelse,
+%D doifalldefinedelse}
+%D
+%D The standard way of testing if a macro is defined is comparing its meaning with
+%D another undefined one, usually \type{\undefined}. To garantee correct working of
+%D the next set of macros, \type{\undefined} may never be defined!
+%D
+%D \starttyping
+%D \doifundefined {string} {...}
+%D \doifdefined {string} {...}
+%D \doifundefinedelse {string} {then ...} {else ...}
+%D \doifdefinedelse {string} {then ...} {else ...}
+%D \doifalldefinedelse {commalist} {then ...} {else ...}
+%D \stoptyping
+%D
+%D Every macroname that \TEX\ builds gets an entry in the hash table, which is of
+%D limited size. It is expected that \ETEX\ will offer a less memory||consuming
+%D alternative.
+
+%D Although it will probably never be a big problem, it is good to be aware of the
+%D difference between testing on a macro name to be build by using \type{\csname} and
+%D \type{\endcsname} and testing the \type{\name} directly.
+%D
+%D \starttyping
+%D \expandafter\ifx\csname NameA\endcsname\relax ... \else ... \fi
+%D
+%D \ifundefined\NameB ... \else ... \fi
+%D \stoptyping
+
+% \suppressifcsnameerror\plusone % already set
+
+\def\doifelseundefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments
+ \fi}
+
+\def\doifelsedefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifundefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\gobbleoneargument\else\expandafter\firstofoneargument
+ \fi}
+
+\def\doifdefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\firstofoneargument\else\expandafter\gobbleoneargument
+ \fi}
+
+\let\doifundefinedelse\doifelseundefined
+\let\doifdefinedelse \doifelsedefined
+
+%D \macros
+%D {letbeundefined}
+%D
+%D Testing for being undefined comes down to testing on \type {\relax} when we use
+%D \type {\csname}, but when using \type {\ifx}, we test on being \type
+%D {\undefined}! In \ETEX\ we have \type {\ifcsname} and that way of testing on
+%D existance is not the same as the one described here. Therefore we introduce:
+
+\unexpanded\def\letbeundefined#1% potential stack buildup when used \global
+ {\expandafter\let\csname#1\endcsname\undefined} % or use \undefinevalue to match \setvalue
+
+\unexpanded\def\localundefine#1% conditional
+ {\ifcsname#1\endcsname\expandafter\let\csname#1\endcsname\undefined\fi}
+
+\unexpanded\def\globalundefine#1% conditional
+ {\ifcsname#1\endcsname\expandafter\glet\csname#1\endcsname\undefined\fi}
+
+%D Beware, being \type {\undefined} in \ETEX\ means that the macro {\em is} defined!
+%D
+%D When we were developing the scientific units module, we encountered different
+%D behavior in text and math mode, which was due to this grouping subtilities. We
+%D therefore decided to use \type{\begingroup} instead of \type{\bgroup}.
+
+\unexpanded\def\doifelsealldefined#1%
+ {\begingroup
+ \donetrue % we could use a reserved one and avoid the group
+ \processcommalist[#1]\syst_helpers_do_if_all_defined_else
+ \ifdone
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifalldefinedelse\doifelsealldefined
+
+\def\syst_helpers_do_if_all_defined_else#1%
+ {\ifcsname#1\endcsname\else
+ \donefalse
+ \expandafter\quitcommalist % added
+ \fi}
+
+%D \macros
+%D {doif,doifelse,doifnot}
+%D
+%D Programming in \TEX\ differs from programming in procedural languages like
+%D \MODULA. This means that one --- well, let me speek for myself --- tries to do
+%D the things in the well known way. Therefore the next set of \type{\ifthenelse}
+%D commands were between the first ones we needed. A few years later, the opposite
+%D became true: when programming in \MODULA, I sometimes miss handy things like
+%D grouping, runtime redefinition, expansion etc. While \MODULA\ taught me to
+%D structure, \TEX\ taught me to think recursive.
+%D
+%D \starttyping
+%D \doif {string1} {string2} {...}
+%D \doifnot {string1} {string2} {...}
+%D \doifelse {string1} {string2} {then ...}{else ...}
+%D \stoptyping
+
+\unexpanded\def\doifelse#1#2%
+ {\iftok{#1}{#2}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doif#1#2%
+ {\iftok{#1}{#2}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnot#1#2%
+ {\iftok{#1}{#2}%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {doifempty,doifemptyelse,doifnotempty}
+%D
+%D We complete our set of conditionals with:
+%D
+%D \starttyping
+%D \doifempty {string} {...}
+%D \doifnotempty {string} {...}
+%D \doifemptyelse {string} {then ...} {else ...}
+%D \stoptyping
+%D
+%D This time, the string is not expanded.
+
+\unexpanded\def\doifelseempty#1%
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifemptyelse\doifelseempty
+
+\unexpanded\def\doifempty#1%
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotempty#1%
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {doifinset,doifnotinset,doifinsetelse}
+%D
+%D We can check if a string is present in a comma separated set of strings.
+%D Depending on the result, some action is taken.
+%D
+%D \starttyping
+%D \doifinset {string} {string,...} {...}
+%D \doifnotinset {string} {string,...} {...}
+%D \doifinsetelse {string} {string,...} {then ...} {else ...}
+%D \stoptyping
+
+% !0nop=\doifinsetelse{ccc}{,}{yes}{nop}
+% !0nop=\doifinsetelse{ccc}{,,}{yes}{nop}
+% !0nop=\doifinsetelse{ccc}{,,,}{yes}{nop}
+
+% !1nop=\doifinsetelse{}{}{yes}{nop}
+% !2yes=\doifinsetelse{aaa}{bbb,ccc,ddd,aaa,eee}{yes}{nop}
+% !3nop=\doifinsetelse{aaa}{bbb}{yes}{nop}
+% !4yes=\doifinsetelse{aaa}{aaa}{yes}{nop}
+% !5nop=\doifinsetelse{aaaa}{bbb,ccc,ddd,aaa,eee}{yes}{nop}
+% !6nop=\doifinsetelse{}{}{yes}{nop}
+% !7nop=\doifinsetelse{}{aaa}{yes}{nop}
+% !8nop=\doifinsetelse{aaa}{}{yes}{nop}
+
+% !1=\doifinset{}{}{yes}
+% !2yes=\doifinset{aaa}{bbb,ccc,ddd,aaa,eee}{yes}
+% !3=\doifinset{aaa}{bbb}{yes}
+% !4yes=\doifinset{aaa}{aaa}{yes}
+% !5=\doifinset{}{}{yes}
+% !6=\doifinset{aaa}{}{yes}
+
+% !1yes=\doifnotinset{}{}{yes}
+% !2=\doifnotinset{aaa}{bbb,ccc,ddd,aaa,eee}{yes}
+% !3yes=\doifnotinset{aaa}{bbb}{yes}
+% !4=\doifnotinset{aaa}{aaa}{yes}
+% !5yes=\doifnotinset{}{}{yes}
+% !6yes=\doifnotinset{aaa}{}{yes}
+
+\unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}}
+\unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}}
+\unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}}
+ % \let\firstinset \clf_firstinset
+
+\let\doifinsetelse\doifelseinset
+
+%D \macros
+%D {doifcommon,doifnotcommon,doifcommonelse}
+%D
+%D Probably the most time consuming tests are those that test for overlap in sets
+%D of strings.
+%D
+%D \starttyping
+%D \doifcommon {string,...} {string,...} {...}
+%D \doifnotcommon {string,...} {string,...} {...}
+%D \doifcommonelse {string,...} {string,...} {then ...} {else ...}
+%D \stoptyping
+
+% !1yes=\doifcommonelse{aaa,bbb,ccc}{aaa,bbb,ccc}{yes}{nop}
+% !2nop=\doifcommonelse{aaa,bbb,ccc}{ddd,eee,fff}{yes}{nop}
+% !3nop=\doifcommonelse{aaa}{ddd,eee,fff}{yes}{nop}
+% !4yes=\doifcommonelse{aaa}{aaa}{yes}{nop}
+% !5nop=\doifcommonelse{bbb}{aaa}{yes}{nop}
+% !6nop=\doifcommonelse{}{aaa,bbb,ccc}{yes}{nop}
+% !7nop=\doifcommonelse{aaa,bbb,ccc}{}{yes}{nop}
+% !8nop=\doifcommonelse{}{}{yes}{nop}
+
+% !9nop=\doifcommonelse{,,}{,,}{yes}{nop}
+% !9yes=\doifcommonelse{,a,}{,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,,a,}{,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,a,}{,,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,a,}{,,,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,,a,}{,,,a,}{yes}{nop}
+
+\unexpanded\def\doifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}}
+\unexpanded\def\doifcommon #1#2{\clf_doifcommon {#1}{#2}}
+\unexpanded\def\doifnotcommon #1#2{\clf_doifnotcommon {#1}{#2}}
+
+\let\doifcommonelse\doifelsecommon
+
+%D \macros
+%D {processcommalist,processcommacommand,quitcommalist,
+%D processcommalistwithparameters}
+%D
+%D We've already seen some macros that take care of comma separated lists. Such
+%D list can be processed with
+%D
+%D \starttyping
+%D \processcommalist[string,string,...]\commando
+%D \stoptyping
+%D
+%D The user supplied command \type{\commando} receives one argument: the string.
+%D This command permits nesting and spaces after commas are skipped. Empty sets
+%D are no problem.
+%D
+%D \startbuffer
+%D \def\dosomething#1{(#1)}
+%D
+%D 1: \processcommalist [\hbox{$a,b,c,d,e,f$}] \dosomething \par
+%D 2: \processcommalist [{a,b,c,d,e,f}] \dosomething \par
+%D 3: \processcommalist [{a,b,c},d,e,f] \dosomething \par
+%D 4: \processcommalist [a,b,{c,d,e},f] \dosomething \par
+%D 5: \processcommalist [a{b,c},d,e,f] \dosomething \par
+%D 6: \processcommalist [{a,b}c,d,e,f] \dosomething \par
+%D 7: \processcommalist [] \dosomething \par
+%D 8: \processcommalist [{[}] \dosomething \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Before we show the result, we present the macro's:
+
+\newcount\commalevel
+
+\installsystemnamespace{nextcommalevel}
+
+\def\syst_helpers_do_do_do_process_comma_item
+ {\csname\??nextcommalevel\the\commalevel\endcsname}
+
+% \ifcase\contextlmtxmode
+
+ \def\syst_helpers_do_process_comma_item
+ {\futurelet\nexttoken\syst_helpers_do_do_process_comma_item}
+
+ \def\syst_helpers_do_do_process_comma_item
+ {\ifx\nexttoken\blankspace
+ \expandafter\syst_helpers_re_do_process_comma_item
+ \else
+ \expandafter\syst_helpers_do_do_process_comma_item_indeed
+ \fi}
+
+ \def\syst_helpers_do_do_process_comma_item_indeed
+ {\ifx\nexttoken]%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\syst_helpers_do_do_do_process_comma_item
+ \fi}
+
+% \else
+%
+% \def\syst_helpers_do_process_comma_item
+% {\futureexpandis]\gobbleoneargument\syst_helpers_do_do_do_process_comma_item}
+%
+% \fi
+
+%D Empty arguments are not processed. Empty items (\type {,,}) however are
+%D treated. We have to check for the special case \type {[{a,b,c}]}.
+
+\unexpanded\def\processcommalist[%
+ {\futurelet\nexttoken\syst_helpers_do_check_comma_item}
+
+\def\syst_helpers_do_check_comma_item
+ {\ifx\nexttoken]%
+ \expandafter\gobblethreearguments
+ \else
+ \expandafter\syst_helpers_do_process_comma_list
+ \fi
+ \relax} % this one preserved the next {}
+
+\def\syst_helpers_do_process_comma_list#1]#2%
+ {\global\advance\commalevel \plusone
+ \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname##1,%
+ {#2{##1}\syst_helpers_do_process_comma_item}%
+ \syst_helpers_do_do_process_comma_item_gobble#1,]\relax
+ \global\advance\commalevel \minusone }
+
+\def\syst_helpers_do_do_process_comma_item_gobble#1{\syst_helpers_do_do_process_comma_item}
+
+%D One way of quitting a commalist halfway is:
+
+\unexpanded\def\quitcommalist
+ {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list}
+
+\def\syst_helpers_do_quit_comma_list#1]%
+ {\endgroup}
+
+\unexpanded\def\quitprevcommalist
+ {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_prev_comma_list}
+
+\def\syst_helpers_do_quit_prev_comma_list#1]%
+ {\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list}
+
+%D The hack we used for checking the next character \type {\doifnextcharelse}
+%D is also used here.
+
+% \ifcase\contextlmtxmode
+
+ \let\next\:
+
+ \def\:{\syst_helpers_re_do_process_comma_item} % \:not saved ?
+
+ \expandafter\def\: {\futurelet\nexttoken\syst_helpers_do_do_process_comma_item}
+
+ \let\:\next
+
+% \fi
+
+%D The previous examples lead to:
+%D
+%D \getbuffer
+
+%D When a list is saved in a macro, we can use a construction like:
+%D
+%D \starttyping
+%D \expandafter\processcommalist\expandafter[\list]\command
+%D \stoptyping
+%D
+%D Such solutions suit most situations, but we wanted a bit more.
+%D
+%D \starttyping
+%D \processcommacommand[string,\stringset,string]\commando
+%D \stoptyping
+%D
+%D where \type{\stringset} is a predefined set, like:
+%D
+%D \starttyping
+%D \def\first{aap,noot,mies}
+%D \def\second{laatste}
+%D
+%D \processcommacommand[\first]\message
+%D \processcommacommand[\first,second,third]\message
+%D \processcommacommand[\first,between,\second]\message
+%D \stoptyping
+%D
+%D Commands that are part of the list are expanded, so the use of this macro has its
+%D limits.
+
+\unexpanded\def\processcommacommand[#1]%
+ {\normalexpanded{\processcommalist[#1]}}
+
+%D The argument to \type{\command} is not delimited. Because we often use \type {[]}
+%D as delimiters, we also have:
+%D
+%D \starttyping
+%D \processcommalistwithparameters[string,string,...]\command
+%D \stoptyping
+%D
+%D where \type{\command} looks like:
+%D
+%D \starttyping
+%D \def\command[#1]{... #1 ...}
+%D \stoptyping
+
+\unexpanded\def\processcommalistwithparameters[#1]#2%
+ {\def\syst_helpers_do_process_comma_list_with_parameters##1{#2[##1]}%
+ \processcommalist[#1]\syst_helpers_do_process_comma_list_with_parameters}
+
+%D \macros
+%D {startprocesscommalist,startprocesscommacommand}
+%D
+%D Two more:
+
+\let\syst_helpers_comma_list_step\relax
+
+\unexpanded\def\startprocesscommalist[#1]#2\stopprocesscommalist
+ {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}%
+ \processcommalist[#1]\syst_helpers_comma_list_step}
+
+\unexpanded\def\startprocesscommacommand[#1]#2\stopprocesscommacommand
+ {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_comma_list_step}
+
+\let\stopprocesscommalist \relax
+\let\stopprocesscommacommand\relax
+
+%D \macros
+%D {processaction,
+%D processfirstactioninset,
+%D processallactionsinset}
+%D
+%D \CONTEXT\ makes extensive use of a sort of case or switch command. Depending of
+%D the presence of one or more provided items, some actions is taken. These macros
+%D can be nested without problems.
+%D
+%D \starttyping
+%D \processaction [x] [a=>\a,b=>\b,c=>\c]
+%D \processfirstactioninset [x,y,z] [a=>\a,b=>\b,c=>\c]
+%D \processallactionsinset [x,y,z] [a=>\a,b=>\b,c=>\c]
+%D \stoptyping
+%D
+%D We can supply both a \type {default} action and an action to be undertaken when
+%D an \type {unknown} value is met:
+%D
+%D \starttyping
+%D \processallactionsinset
+%D [x,y,z]
+%D [ a=>\a,
+%D b=>\b,
+%D c=>\c,
+%D default=>\default,
+%D unknown=>\unknown{... \commalistelement ...}]
+%D \stoptyping
+%D
+%D When \type {#1} is empty, this macro scans list \type {#2} for the keyword \type
+%D {default} and executed the related action if present. When \type {#1} is non
+%D empty and not in the list, the action related to \type {unknown} is executed.
+%D Both keywords must be at the end of list \type{#2}. Afterwards, the actually
+%D found keyword is available in \type {\commalistelement}. An advanced example of
+%D the use of this macro can be found in \PPCHTEX, where we completely rely on \TEX\
+%D for interpreting user supplied keywords like \type {SB}, \type {SB1..6}, \type
+%D {SB125} etc.
+
+\newcount\processlevel
+
+\unexpanded\def\syst_helpers_do_compare_process_action_a[#1=>#2][#3]%
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\s!default
+ \let\commalistelement\empty
+ #2%
+ \fi}
+
+% met \quitcommalist tot meer dan 25\% sneller
+
+\unexpanded\def\syst_helpers_do_compare_process_action_b[#1=>#2][#3]%
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \def\commalistelement{#3}%
+ #2%
+ \expandafter\quitcommalist
+ \orelse\ifx\m_syst_string_two\s!unknown
+ \def\commalistelement{#3}% beware of loops
+ #2%
+ \fi}
+
+\unexpanded\def\processaction[#1]#2[%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_a
+ \else
+ \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_b
+ \fi
+ \edef\syst_helpers_do_process_action##1{\syst_helpers_do_compare_process_action[##1][#1]}% expands #1
+ \processnextcommalist\relax\relax\syst_helpers_do_process_action[}
+
+\unexpanded\def\syst_helpers_do_compare_process_action_c[#1=>#2][#3]%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#3}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \def\commalistelement{#3}%
+ #2%
+ \expandafter\quitprevcommalist
+ \else
+ \edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\s!unknown
+ \def\commalistelement{#3}%
+ #2%
+ \fi
+ \fi}
+
+\unexpanded\def\processfirstactioninset[#1]%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\processaction
+ \else
+ \expandafter\syst_helpers_process_first_action_in_set_indeed
+ \fi
+ [#1]}
+
+\unexpanded\def\syst_helpers_process_first_action_in_set_indeed[#1]#2[#3]%
+ {\def\syst_helpers_do_process_action##1%
+ {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_c[####1][##1]}%
+ \processcommalist[#3]\syst_helpers_do_do_process_action}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action}
+
+\unexpanded\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#3}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \def\commalistelement{#3}%
+ #2%
+ \expandafter\quitcommalist
+ \else
+ \edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\s!unknown
+ \def\commalistelement{#3}%
+ #2%
+ \fi
+ \fi}
+
+\installsystemnamespace{nextactionlevel}
+
+\unexpanded\def\syst_helpers_do_process_all_actions_in_set
+ {\csname\??nextactionlevel\the\processlevel\endcsname}
+
+\unexpanded\def\processallactionsinset[#1]%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\processaction
+ \else
+ \expandafter\syst_helpers_process_all_actions_in_set_indeed
+ \fi
+ [#1]}
+
+\unexpanded\def\syst_helpers_process_all_actions_in_set_indeed[#1]#2[#3]%
+ {\advance\processlevel \plusone
+ \expandafter\def\csname\??nextactionlevel\the\processlevel\endcsname##1%
+ {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_d[####1][##1]}%
+ \processcommalist[#3]\syst_helpers_do_do_process_action}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_all_actions_in_set
+ \advance\processlevel\minusone}
+
+%D These macros use:
+
+\unexpanded\def\processnextcommalist#1#2#3[#4#5]%
+ {#1%
+ \let\nexttoken#4%
+ \global\advance\commalevel \plusone
+ \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname##1,%
+ {#3{##1}\syst_helpers_do_process_comma_item}%
+ \syst_helpers_do_do_process_comma_item#4#5,]\relax
+ \global\advance\commalevel\minusone
+ #2}
+
+%D \macros
+%D {getfirstcharacter, firstcharacter, remainingcharacters, doiffirstcharacter}
+%D
+%D Sometimes the action to be undertaken depends on the next character. This macro
+%D get this character and puts it in \type {\firstcharacter}.
+%D
+%D \starttyping
+%D \getfirstcharacter {string}
+%D \stoptyping
+%D
+%D A two step expansion is used to prevent problems with complicated arguments, for
+%D instance arguments that consist of two or more expandable tokens.
+
+\let\firstcharacter \empty
+\let\remainingcharacters\empty
+
+\unexpanded\def\getfirstcharacter #1{\clf_getfirstcharacter{#1}}
+\unexpanded\def\doifelsefirstchar #1#2{\clf_doifelsefirstchar{#1}{#2}}
+\unexpanded\def\thefirstcharacter #1{\clf_thefirstcharacter{#1}}
+\unexpanded\def\theremainingcharacters#1{\clf_theremainingcharacters{#1}}
+
+\let\doiffirstcharelse\doifelsefirstchar
+
+%D \macros
+%D {doifinstringelse, doifincsnameelse}
+%D
+%D We can check for the presence of a substring in a given sequence of characters.
+%D
+%D \starttyping
+%D \doifinsetelse {substring} {string} {then ...} {else ...}
+%D \stoptyping
+
+\let\m_syst_sub_string\empty
+
+\unexpanded\def\doifelseinstring#1%
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
+ \expandafter\thirdofthreearguments
+ \else
+ \expandafter\syst_helpers_do_if_in_string_else_indeed
+ \fi}
+
+\let\doifinstringelse\doifelseinstring
+
+\unexpanded\def\syst_helpers_do_if_in_string_else_indeed#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifinstring#1%%
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
+ \expandafter\gobbletwoarguments
+ \else
+ \expandafter\syst_helpers_do_if_in_string_indeed
+ \fi}
+
+\unexpanded\def\syst_helpers_do_if_in_string_indeed#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotinstring#1%%
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
+ \expandafter\gobbletwoarguments
+ \else
+ \expandafter\syst_helpers_do_if_not_in_string_indeed
+ \fi}
+
+\unexpanded\def\syst_helpers_do_if_not_in_string_indeed#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+% replaces prev
+
+\unexpanded\def\syst_helpers_do_if_in_string_else#1#2% ##2 can be {abc}
+ {\expandafter\def\expandafter\syst_helpers_do_do_if_in_string_else
+ \expandafter##\expandafter1#1##2##3^^^^0004{\unless\if##2@}% expand #1 here
+ \expandafter\syst_helpers_do_do_if_in_string_else\normalexpanded{#2#1}@@^^^^0004} % expand #2 here
+
+%D The next alternative proved to be upto twice as fast on tasks like checking
+%D reserved words in pretty verbatim typesetting! This is mainly due to the fact
+%D that passing (expanded) strings is much slower that passing a macro.
+%D
+%D \starttyping
+%D \doifincsnameelse {substring} {\string} {then ...} {else ...}
+%D \stoptyping
+%D
+%D Where \type {\doifinstringelse} does as much expansion as possible, the latter
+%D alternative does minimal (one level) expansion.
+
+\unexpanded\def\syst_helpers_do_if_in_csname_else#1#2%
+ {\def\syst_helpers_do_do_if_in_csname_else##1#1##2##3^^^^0004%
+ {\unless\if##2@}%
+ \expandafter\syst_helpers_do_do_if_in_csname_else#2#1@@^^^^0004}
+
+\unexpanded\def\doifelseincsname#1#2%
+ {\normalexpanded{\syst_helpers_do_if_in_csname_else{#1}}{#2}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifincsnameelse\doifelseincsname
+
+%D \macros
+%D {doifnumberelse,doifnumber,doifnotnumber}
+%D
+%D The next macro executes a command depending of the outcome of a test on numerals.
+%D This is probably one of the fastest test possible, exept from a less robust
+%D 10||step \type {\if}||ladder or some tricky \type {\lcode} checking.
+%D
+%D \starttyping
+%D \doifnumberelse {string} {then ...} {else ...}
+%D \stoptyping
+%D
+%D The macro accepts \type {123}, \type {abc}, \type {{}}, \type {\getal} and \type
+%D {\the\count...}. This macro is a rather dirty one.
+
+\def\doifelsenumber#1%
+ {\ifchknum#1\or
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifnumber#1%
+ {\ifchknum#1\or
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doifnotnumber#1%
+ {\ifchknum#1\or
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\let\doifnumberelse\doifelsenumber
+
+%D \macros
+%D {setpercentdimen}
+%D
+%D \starttyping
+%D \scratchdimen=100pt \setpercentdimen\scratchdimen{10\letterpercent}
+%D \scratchdimen=100pt \setpercentdimen\scratchdimen{5pt}
+%D \scratchdimen \percentdimen \hsize {10\letterpercent}
+%D \stoptyping
+
+\def\percentdimen#1#2% dimen percentage (with %)
+ {\dimexpr\clf_percentageof{#2}\dimexpr#1\relax}
+
+\unexpanded\def\setpercentdimen#1#2% dimen percentage (with %)
+ {#1=\clf_percentageof{#2}\dimexpr#1\relax}
+
+%D \macros
+%D {makerawcommalist,
+%D rawdoinsetelse,
+%D rawprocesscommalist,
+%D rawprocessaction}
+%D
+%D Some of the commands mentioned earlier are effective but slow. When one is
+%D desperately in need of faster alternatives and when the conditions are
+%D predictable safe, the \type {\raw} alternatives come into focus. A major drawback
+%D is that they do not take \type {\c!constants} into account, simply because no
+%D expansion is done. This is no problem with \type {\rawprocesscommalist}, because
+%D this macro does not compare anything. Expandable macros are permitted as search
+%D string.
+%D
+%D \starttyping
+%D \makerawcommalist[string,string,...]\stringlist
+%D \rawdoifelseinset{string}{string,...}{...}{...}
+%D \rawprocesscommalist[string,string,...]\commando
+%D \rawprocessaction[x][a=>\a,b=>\b,c=>\c]
+%D \stoptyping
+%D
+%D Spaces embedded in the list, for instance after commas, spoil the search process.
+%D The gain in speed depends on the length of the argument (the longer the argument,
+%D the less we gain).
+
+\unexpanded\def\makerawcommalist[#1]#2% use \processnext ... here
+ {\def\syst_helpers_do_make_raw_comma_list##1% we don't expand ##1
+ {\ifx#2\empty
+ \def#2{##1}%
+ \else
+ \expandafter\def\expandafter#2\expandafter{#2,##1}%
+ \fi}%
+ \let#2\empty
+ \processcommalist[#1]\syst_helpers_do_make_raw_comma_list}
+
+\def\syst_helpers_raw_process_comma_item#1,#2% #2 eats up preceding space
+ {\if]#1\else
+ \csname\??nextcommalevel\the\commalevel\endcsname{#1}%
+ \expandafter\syst_helpers_raw_process_comma_item
+ \fi#2}
+
+\unexpanded\def\rawprocesscommalist[#1]#2% accepteert ook [\cs]
+ {\global\advance\commalevel \plusone
+ \expandafter\let\csname\??nextcommalevel\the\commalevel\endcsname#2%
+ \expandafter\syst_helpers_raw_process_comma_item#1,],% \relax
+ \global\advance\commalevel \minusone }
+
+\unexpanded\def\rawprocesscommacommand[#1]% not really needed
+ {\normalexpanded{\rawprocesscommalist[#1]}}
+
+%D Here is one without nesting:
+
+\unexpanded\def\syst_helpers_fast_process_comma_item#1,#2% #2 eats up preceding space
+ {\if]#1\else
+ \syst_helpers_fast_process_comma_command{#1}%
+ \expandafter\syst_helpers_fast_process_comma_item
+ \fi#2}
+
+\unexpanded\def\fastprocesscommalist[#1]#2% accepteert ook [\cs]
+ {\let\syst_helpers_fast_process_comma_command#2%
+ \expandafter\syst_helpers_fast_process_comma_item#1,],}% \relax
+
+\unexpanded\def\fastprocesscommacommand[#1]#2% accepteert ook [\cs]
+ {\let\syst_helpers_fast_process_comma_command#2%
+ \normalexpanded{\syst_helpers_fast_process_comma_item#1},],}% \relax
+
+% \def\rawdoifelseinset#1#2{\doifinstringelse{,#1,}{,#2,}}
+% \def\rawdoifinset #1#2{\doifinstring {,#1,}{,#2,}}
+
+\def\m_syst_two_commas{,,}
+
+\unexpanded\def\rawdoifelseinset#1%
+ {\edef\m_syst_sub_string{,#1,}% expand #1 here
+ \ifx\m_syst_sub_string\m_syst_two_commas
+ \expandafter\thirdofthreearguments
+ \else
+ \expandafter\syst_helpers_raw_do_if_in_set_else
+ \fi}
+
+\let\rawdoifinsetelse\rawdoifinsetelse
+
+\unexpanded\def\syst_helpers_raw_do_if_in_set_else#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\rawdoifinset#1%
+ {\edef\m_syst_sub_string{,#1,}% expand #1 here
+ \ifx\m_syst_sub_string\m_syst_two_commas
+ \expandafter\gobbletwoarguments
+ \else
+ \expandafter\syst_helpers_raw_do_if_in_set
+ \fi}
+
+\unexpanded\def\syst_helpers_raw_do_if_in_set#1%%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D Some more raw material:
+
+\def\syst_helpers_do_raw_process_action[#1][#2]%
+ {\def\syst_helpers_do_do_raw_process_action##1,#1=>##2,##3^^^^0004%
+ {\if##3@\else
+ \def\m_syst_helpers_process_action{##2}%
+ \fi}%
+ \syst_helpers_do_do_raw_process_action,#2,#1=>,@^^^^0004}
+
+\unexpanded\def\rawprocessaction[#1]#2[#3]%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{undefined}% better \!!undefined
+ \let\m_syst_helpers_process_action\m_syst_string_two
+ \ifx\m_syst_string_one\empty
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!default][#3]%
+ \else
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\m_syst_string_one][#3]%
+ \ifx\m_syst_helpers_process_action\m_syst_string_two
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!unknown][#3]%
+ \fi
+ \fi
+ \ifx\m_syst_helpers_process_action\m_syst_string_two
+ \else
+ \m_syst_helpers_process_action
+ \fi}
+
+%D When we process the list \type {a,b,c,d,e}, the raw routine takes over 30\% less
+%D time, when we feed $20+$ character strings we gain about 20\%. Alternatives which
+%D use \type {\futurelet} perform worse. Part of the speedup is due to the \type
+%D {\let} and \type {\expandafter} in the test.
+%D
+%D \macros
+%D {dosetvalue,dosetevalue,dosetgvalue,docopyvalue,doresetvalue,
+%D dogetvalue}
+%D
+%D When we are going to do assignments, we have to take multi||linguality into account.
+%D For the moment we keep things simple and single||lingual.
+%D
+%D \starttyping
+%D \dosetvalue {label} {variable} {value}
+%D \dosetevalue {label} {variable} {value}
+%D \dosetgvalue {label} {variable} {value}
+%D \docopyvalue {to label} {from label} {variable}
+%D \doresetvalue {label} {variable}
+%D \stoptyping
+%D
+%D These macros are in fact auxiliary ones and are not meant for use outside the
+%D assignment macros.
+
+\def\dosetvalue#1#2% #3
+ {\expandafter\def\csname#1#2\endcsname} % {#3}}
+
+\def\dosetevalue#1#2% #3
+ {\expandafter\edef\csname#1#2\endcsname} % {#3}}
+
+\def\dosetgvalue#1#2% #3
+ {\expandafter\gdef\csname#1#2\endcsname} % {#3}}
+
+\def\doresetvalue#1#2%
+ {\expandafter\let\csname#1#2\endcsname\empty}
+
+\def\doignorevalue#1#2#3%
+ {\expandafter\let\csname#1#2\endcsname\empty}
+
+\def\docopyvalue#1#2#3%
+ {\expandafter\def\csname#1#3\endcsname{\csname#2#3\endcsname}}
+
+%D \macros
+%D {doassign,undoassign,doassignempty}
+%D
+%D Assignments are the backbone of \CONTEXT. Abhorred by the concept of style file
+%D hacking, we took a considerable effort in building a parameterized system.
+%D Unfortunately there is a price to pay in terms of speed. Compared to other
+%D packages and taking the functionality of \CONTEXT\ into account, the total size
+%D of the format file is still very acceptable. Now how are these assignments done.
+%D
+%D Assignments can be realized with:
+%D
+%D \starttyping
+%D \doassign[label][variable=value]
+%D \undoassign[label][variable=value]
+%D \stoptyping
+%D
+%D and:
+%D
+%D \starttyping
+%D \doassignempty[label][variable=value]
+%D \stoptyping
+%D
+%D Assignments like \type{\doassign} are compatible with:
+%D
+%D \starttyping
+%D \def\labelvariable{value}
+%D \stoptyping
+%D
+%D We do check for the presence of an \type{=} and loudly complain of it's missed. We
+%D will redefine this macro later on, when a more advanced message mechanism is
+%D implemented.
+
+\newif\iferrorisfatal
+
+\unexpanded\def\waitonfatalerror
+ {\iferrorisfatal\wait\fi}
+
+\unexpanded\def\showassignerror#1#2%
+ {\writestatus{setup}{missing or ungrouped '=' after '#1' in line #2}%
+ \waitonfatalerror}
+
+\unexpanded\def\doassignempty[#1][#2=#3]%
+ {\ifcsname#1#2\endcsname\else\dosetvalue{#1}{#2}{#3}\fi}
+
+%D \macros
+%D {getparameters,geteparameters,getgparameters,
+%D forgetparameters}
+%D
+%D Using the assignment commands directly is not our ideal of user friendly interfacing,
+%D so we take some further steps.
+%D
+%D \starttyping
+%D \getparameters [label] [...=...,...=...]
+%D \forgetparameters [label] [...=...,...=...]
+%D \stoptyping
+%D
+%D Again, the label identifies the category a variable belongs to. The second argument
+%D can be a comma separated list of assignments.
+%D
+%D \starttyping
+%D \getparameters
+%D [demo]
+%D [alfa=1,
+%D beta=2]
+%D \stoptyping
+%D
+%D is equivalent to
+%D
+%D \starttyping
+%D \def\demoalfa{1}
+%D \def\demobeta{2}
+%D \stoptyping
+%D
+%D
+%D In the pre||multi||lingual stadium \CONTEXT\ took the next approach. With
+%D
+%D \starttyping
+%D \def\??demo {@@demo}
+%D \def\!!alfa {alfa}
+%D \def\!!beta {beta}
+%D \stoptyping
+%D
+%D calling
+%D
+%D \starttyping
+%D \getparameters
+%D [\??demo]
+%D [\!!alfa=1,
+%D \!!beta=2]
+%D \stoptyping
+%D
+%D lead to:
+%D
+%D \starttyping
+%D \def\@@demoalfa{1}
+%D \def\@@demobeta{2}
+%D \stoptyping
+%D
+%D Because we want to be able to distinguish the \type{!!} pre||tagged user supplied
+%D variables from internal counterparts, we will introduce a slightly different tag
+%D in the multi||lingual modules. There we will use \type{c!} or \type{v!},
+%D depending on the context.
+%D
+%D By calling \type{doassign} directly, we save ourselves some argument passing
+%D and gain some speed. Whatever optimizations we do, this command will always be
+%D one of the bigger bottlenecks. The alternative \type{\geteparameters} --- it's
+%D funny to see that this alternative saw the light so lately --- can be used to do
+%D expanded assigments.
+
+\let\currentvalue\empty
+
+\unexpanded\def\getparameters {\dogetparameters\dosetvalue}
+\unexpanded\def\geteparameters {\dogetparameters\dosetevalue}
+\unexpanded\def\getgparameters {\dogetparameters\dosetgvalue}
+\unexpanded\def\getxparameters {\dogetparameters\dosetxvalue}
+\unexpanded\def\forgetparameters{\dogetparameters\doignorevalue}
+
+\let\getexpandedparameters\geteparameters
+
+\unexpanded\def\dogetparameters#1[#2]#3[#4%
+ {\if\noexpand#4]%
+ \expandafter\gobbleoneargument
+ \else
+ \let\setsomevalue#1%
+ \def\syst_helpers_get_parameters_assign{\syst_helpers_get_parameters_assign_indeed#2}%
+ \expandafter\syst_helpers_get_parameters
+ \fi#4}
+
+\def\syst_helpers_get_parameters#1]%
+ {\xprocesscommaitem#1,],^^^^0004}
+
+\def\syst_helpers_process_comma_item#1,#2% #2 takes space before ,
+ {\if,#1,% dirty trick for testing #1=empty
+ \expandafter\syst_helpers_process_comma_item
+ \orelse\if]#1%
+ \expandafter\gobbleoneargument
+ \else
+ \syst_helpers_get_parameters_assign^^^^0004#1==\empty^^^^0004%
+ \expandafter\syst_helpers_process_comma_item
+ \fi#2}
+
+\def\syst_helpers_assign_error#1#2#3%
+ {\showassignerror{#2}{\the\inputlineno\space(#1)}}
+
+\def\syst_helpers_get_parameters_assign_normal#1^^^^0004#2=#3=#4#5^^^^0004%
+ {\ifx\empty#2\empty
+ \expandafter\syst_helpers_assign_error
+ \orelse\ifx#4\empty
+ \expandafter\syst_helpers_assign_error
+ \else
+ \expandafter\setsomevalue
+ \fi
+ {#1}{#2}{#3}}
+
+\def\syst_helpers_get_parameters_assign_error#1^^^^0004#2=#3=#4#5^^^^0004%
+ {\ifx\empty#2\empty
+ \expandafter\syst_helpers_assign_error
+ \orelse\ifx#4\empty
+ \expandafter\syst_helpers_assign_error
+ \orelse\ifcsname#1#2\endcsname
+ \expandafter\let\expandafter\currentvalue\csname#1#2\endcsname
+ \expandafter\setsomevalue
+ \else
+ \let\currentvalue\empty
+ \expandafter\setsomevalue
+ \fi
+ {#1}{#2}{#3}}
+
+\let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal
+
+\unexpanded\def\doassign [#1][#2]{\let\setsomevalue\dosetvalue \syst_helpers_get_parameters_assign_indeed#1^^^^0004#2==\empty^^^^0004}
+\unexpanded\def\doeassign [#1][#2]{\let\setsomevalue\dosetevalue \syst_helpers_get_parameters_assign_indeed#1^^^^0004#2==\empty^^^^0004}
+\unexpanded\def\undoassign[#1][#2]{\let\setsomevalue\doresetvalue\syst_helpers_get_parameters_assign_indeed#1^^^^0004#2==\empty^^^^0004}
+
+%D \macros
+%D {processassignmentlist,processassignmentcommand,
+%D startprocessassignmentlist,startprocessassignmentcommand}
+%D
+%D For Wolfgang:
+%D
+%D \starttyping
+%D \def\showpair#1#2{key:#1, value:#2\par}
+%D \processassignmentlist[a=1,b=2]\showpair
+%D \stoptyping
+%D
+%D We can optimize this one if needed but it's not a core macro so hardly worth the
+%D trouble and tokens.
+
+\unexpanded\def\processassignmentlist[#1]#2% #2 == \command{key}{value]
+ {\def\syst_helpers_process_assignment_entry##1{#2}% {##2}{##3} % namespace is ignored
+ \dogetparameters\syst_helpers_process_assignment_entry[][#1]}
+
+\unexpanded\def\processassignmentcommand[#1]%
+ {\normalexpanded{\processassignmentlist[#1]}}
+
+\unexpanded\def\startprocessassignmentlist[#1]#2\stopprocessassignmentlist
+ {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
+ \processassignmentlist[#1]\currentassignmentlistcommand}
+
+\unexpanded\def\startprocessassignmentcommand[#1]#2\stopprocessassignmentcommand
+ {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
+ \normalexpanded{\processassignmentlist[#1]}\currentassignmentlistcommand}
+
+%D \macros{currentvalue}
+%D
+%D Just in case a \type{\getparameter} argument itself ends up inside a \type
+%D {\write} or other expandable location, our new macro needs a default value.
+%D
+%D \starttyping
+%D \getparameters[xxx][aaa=bbb]\par
+%D \getparameters[xxx][=bbb]\par
+%D \getparameters[xxx][aaa=]\par
+%D \getparameters[xxx][=]\par
+%D \getparameters[xxx][aaa]\par
+%D \stoptyping
+
+%D \macros
+%D {expandparameters}
+%D
+%D Example usage:
+%D
+%D \startbuffer
+%D \getparameters[taco][name=taco]
+%D \convertcommand\taconame\to\ascii \ascii
+%D \expandparameters \getparameters[taco][name=\currentvalue\space hoekwater]
+%D \convertcommand\taconame\to\ascii \ascii
+%D \getparameters[taco][name=\currentvalue\space hoekwater]
+%D \convertcommand\taconame\to\ascii \ascii
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D Here we hook in the code (beware, this is the optimized get **):
+
+\def\syst_helpers_get_parameters_normal#1]%
+ {\syst_helpers_process_comma_item#1,],^^^^0004}
+
+\def\syst_helpers_get_parameters_expanded#1]%
+ {\let\dosetnvalue\setsomevalue
+ \let\setsomevalue\dosetevalue
+ \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_error
+ \let\setsomevalue\dosetevalue
+ \syst_helpers_process_comma_item#1,],^^^^0004%
+ \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal
+ \let\setsomevalue\dosetnvalue
+ \let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal
+ \let\currentvalue\empty}
+
+\let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal % **
+
+\unexpanded\def\expandparameters
+ {\let\syst_helpers_get_parameters\syst_helpers_get_parameters_expanded}
+
+%D \macros
+%D {getemptyparameters}
+%D
+%D Sometimes we explicitly want variables to default to an empty string, so we
+%D welcome:
+%D
+%D \starttyping
+%D \getemptyparameters [label] [...=...,...=...]
+%D \stoptyping
+
+\unexpanded\def\getemptyparameters[#1]#2[#3]%
+ {\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}%
+ \processcommalist[#3]\syst_helpers_get_empty_parameters}
+
+%D \macros
+%D {copyparameters}
+%D
+%D Some \CONTEXT\ commands take their default setups from others. All commands that
+%D are able to provide backgounds or rules around some content, for instance default
+%D to the standard command for ruled boxes. Is situations like this we can use:
+%D
+%D \starttyping
+%D \copyparameters [to-label] [from-label] [name1,name2,...]
+%D \stoptyping
+%D
+%D For instance
+%D
+%D \starttyping
+%D \copyparameters
+%D [internal][external]
+%D [alfa,beta]
+%D \stoptyping
+%D
+%D Leads to:
+%D
+%D \starttyping
+%D \def\internalalfa {\externalalfa}
+%D \def\internalbeta {\externalbeta}
+%D \stoptyping
+%D
+%D By using \type {\docopyvalue} we've prepared this command for use in a
+%D multi||lingual environment.
+
+\unexpanded\def\copyparameters[#1]#2[#3]#4[#5]%
+ {\doifnot{#1}{#3}
+ {\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#3}}% ##1
+ \processcommalist[#5]\syst_helpers_copy_parameter}}
+
+%D \macros
+%D {ifparameters,checkparameters}
+%D
+%D A slightly different one is \type {\checkparameters}, which also checks on the
+%D presence of a~\type {=}.
+%D
+%D The boolean \type {\ifparameters} can be used afterwards. Combining both in one
+%D \type {\if}||macro would lead to problems with nested \type {\if}'s.
+%D
+%D \starttyping
+%D \checkparameters[argument]
+%D \stoptyping
+
+\newif\ifparameters
+
+\def\syst_helpers_check_parameters#1=#2#3^^^^0004%
+ {\if#2^^^^0003\parametersfalse\else\parameterstrue\fi}
+
+\unexpanded\def\checkparameters[#1]%
+ {\syst_helpers_check_parameters#1=^^^^0003^^^^0003^^^^0004}
+
+%D \macros
+%D {getfromcommalist,getfromcommacommand,
+%D commalistelement,
+%D getcommalistsize,getcommacommandsize}
+%D
+%D It's possible to get an element from a commalist or a command representing
+%D a commalist.
+%D
+%D \starttyping
+%D \getfromcommalist [string] [n]
+%D \getfromcommacommand [string,\strings,string,...] [n]
+%D \stoptyping
+%D
+%D The difference betwee the two of them is the same as the difference between
+%D \type {\processcomma...}. The found string is stored in \type
+%D {\commalistelement}.
+%D
+%D We can calculate the size of a comma separated list by using:
+%D
+%D \starttyping
+%D \getcommalistsize [string,string,...]
+%D \getcommacommandsize [string,\strings,string,...]
+%D \stoptyping
+%D
+%D Afterwards, the length is available in the macro \type {\commalistsize}
+%D (not a \COUNTER).
+
+\newcount\commalistcounter
+
+\def\commalistsize{0}
+
+\def\syst_helpers_get_comma_list_size#1%
+ {\advance\commalistcounter\plusone}
+
+\unexpanded\def\getcommalistsize#1]% don't loose [{#1}]
+ {\commalistcounter\zerocount
+ \processcommalist#1]\syst_helpers_get_comma_list_size % was [{#1}]
+ \edef\commalistsize{\the\commalistcounter}}
+
+% \def\getcommacommandsize[#1]%
+% {\edef\commacommand{#1}%
+% \scratchtoks\expandafter{\expandafter[\commacommand]}%
+% \expandafter\getcommalistsize\the\scratchtoks }
+
+\unexpanded\def\getcommacommandsize[#1]%
+ {\normalexpanded{\getcommalistsize[#1]}}
+
+\def\syst_helpers_get_from_comma_list#1%
+ {\advance\commalistcounter \minusone
+ \ifcase\commalistcounter
+ \def\commalistelement{#1}%
+ \expandafter\quitcommalist
+ \fi}
+
+\unexpanded\def\getfromcommalist[#1]#2[#3]%
+ {\let\commalistelement\empty
+ \commalistcounter#3\relax
+ \processcommalist[#1]\syst_helpers_get_from_comma_list}
+
+\unexpanded\def\getfromcommacommand[#1]%
+ {\normalexpanded{\getfromcommalist[#1]}}
+
+%D Watertight (and efficient) solutions are hard to find, due to the handling of
+%D braces during parameters passing and scanning. Nevertheless:
+%D
+%D \startbuffer
+%D \def\dosomething#1{(#1=\commalistsize) }
+%D
+%D \getcommalistsize [\hbox{$a,b,c,d,e,f$}] \dosomething 1
+%D \getcommalistsize [{a,b,c,d,e,f}] \dosomething 1
+%D \getcommalistsize [{a,b,c},d,e,f] \dosomething 4
+%D \getcommalistsize [a,b,{c,d,e},f] \dosomething 4
+%D \getcommalistsize [a{b,c},d,e,f] \dosomething 4
+%D \getcommalistsize [{a,b}c,d,e,f] \dosomething 4
+%D \getcommalistsize [] \dosomething 0
+%D \getcommalistsize [{[}] \dosomething 1
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D reports:
+%D
+%D \getbuffer
+
+%D \macros
+%D {dogetcommalistelement,dogetcommacommandelement}
+%D
+%D For low level (fast) purposes, we can also use the next alternative, which can
+%D handle 8~elements at most.
+%D
+%D \starttyping
+%D \dogetcommalistelement1\from a,b,c\to\commalistelement
+%D \stoptyping
+
+\def\syst_helpers_get_comma_list_element#1\from#2,#3,#4,#5,#6,#7,#8\to#9%
+ {\edef#9{\ifcase#1\relax\or#2\or#3\or#4\or#5\or#6\or#7\or#8\fi}}
+
+\def\dogetcommacommandelement#1\from#2\to%
+ {\expandafter\syst_helpers_get_comma_list_element\expandafter#1\expandafter\from#2,,,,,,\to}
+
+%D \macros
+%D {dosingleargument,dodoubleargument,dotripleargument,
+%D doquadrupleargument,doquintupleargument,dosixtupleargument,
+%D doseventupleargument}
+%D
+%D When working with delimited arguments, spaces and lineendings can interfere. The
+%D next set of macros uses \TEX' internal scanner for grabbing everything between
+%D arguments. Forgive me the funny names.
+%D
+%D \starttyping
+%D \dosingleargument\commando = \commando[#1]
+%D \dodoubleargument\commando = \commando[#1][#2]
+%D \dotripleargument\commando = \commando[#1][#2][#3]
+%D \doquadrupleargument\commando = \commando[#1][#2][#3][#4]
+%D \doquintupleargument\commando = \commando[#1][#2][#3][#4][#5]
+%D \dosixtupleargument\commando = \commando[#1][#2][#3][#4][#5][#6]
+%D \doseventupleargument\command = \commando[#1][#2][#3][#4][#5][#6][#7]
+%D \stoptyping
+%D
+%D These macros are used in the following way:
+%D
+%D \starttyping
+%D \def\dosetupsomething[#1][#2]%
+%D {... #1 ... #2 ...}
+%D
+%D \unexpanded\def\setupsomething
+%D {\dodoubleargument\dosetupsomething}
+%D \stoptyping
+%D
+%D The implementation can be surprisingly simple and needs no
+%D further explanation, like:
+%D
+%D \starttyping
+%D \def\dosingleargument#1[#2]%
+%D {#1[#2]}
+%D \def\dotripleargument#1[#2]#3[#4]#5[#6]%
+%D {#1[#2][#4][#6]}
+%D \def\doquintupleargument#1%
+%D {\def\dodoquintupleargument[##1]##2[##3]##4[##5]##6[##7]##8[##9]%
+%D {#1[##1][##3][##5][##7][##9]}%
+%D \dodoquintupleargument}
+%D \stoptyping
+%D
+%D Because \TEX\ accepts 9~arguments at most, we have to use two||step solution when
+%D getting five or more arguments.
+%D
+%D When developing more and more of the real \CONTEXT, we started using some
+%D alternatives that provided empty arguments (in fact optional ones) whenever the
+%D user failed to supply them. Because this more complicated macros enable us to do
+%D some checking, we reimplemented the non||empty ones.
+
+%D \macros
+%D {iffirstagument,ifsecondargument,ifthirdargument,
+%D iffourthargument,iffifthargument,ifsixthargument,
+%D ifseventhargument}
+%D
+%D We use some signals for telling the calling macros if all wanted arguments are
+%D indeed supplied by the user.
+
+\newif\iffirstargument
+\newif\ifsecondargument
+\newif\ifthirdargument
+\newif\iffourthargument
+\newif\iffifthargument
+\newif\ifsixthargument
+\newif\ifseventhargument
+
+%D \macros
+%D {dosingleempty,dodoubleempty,dotripleempty,
+%D doquadrupleempty,doquintupleempty,dosixtupeempty,
+%D doseventupleempty}
+%D
+%D The empty argument supplying macros mentioned before, look like:
+%D
+%D \starttyping
+%D \dosingleempty \command
+%D \dodoubleempty \command
+%D \dotripleempty \command
+%D \doquadrupleempty \command
+%D \doquintupleempty \command
+%D \dosixtuple_empty \command
+%D \doseventupleempty\command
+%D \stoptyping
+%D
+%D So \type{\dodoubleempty} leads to:
+%D
+%D \starttyping
+%D \command[#1][#2]
+%D \command[#1][]
+%D \command[][]
+%D \stoptyping
+%D
+%D Depending of the generousity of the user. Afterwards one can use the \type
+%D {\if...argument} boolean. For novice: watch the stepwise doubling of \type {#}'s.
+
+%D Common:
+
+\newtoks\t_syst_aux
+
+\def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux}
+\def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux}
+\def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux}
+\def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux}
+\def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux}
+\def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux}
+\def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux}
+
+%D Single:
+
+\unexpanded\def\dosingleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop}
+
+\def\syst_helpers_single_empty_one_nop
+ {\firstargumentfalse
+ \the\t_syst_aux[]}
+
+%D Double
+
+\unexpanded\def\dodoubleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop}
+
+\def\syst_helpers_double_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop}
+
+\def\syst_helpers_double_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \the\t_syst_aux[][]}
+
+\def\syst_helpers_double_empty_two_nop
+ {\secondargumentfalse
+ \the\t_syst_aux[]}
+
+% Triple
+
+\unexpanded\def\dotripleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop}
+
+\def\syst_helpers_triple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop}
+
+\def\syst_helpers_triple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop}
+
+\def\syst_helpers_triple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \the\t_syst_aux[][][]}
+
+\def\syst_helpers_triple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \the\t_syst_aux[][]}
+
+\def\syst_helpers_triple_empty_three_nop
+ {\thirdargumentfalse
+ \the\t_syst_aux[]}
+
+%D Quadruple:
+
+\unexpanded\def\doquadrupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop}
+
+\def\syst_helpers_quadruple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop}
+
+\def\syst_helpers_quadruple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop}
+
+\def\syst_helpers_quadruple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop}
+
+\def\syst_helpers_quadruple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \the\t_syst_aux[][][][]}
+
+\def\syst_helpers_quadruple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \the\t_syst_aux[][][]}
+
+\def\syst_helpers_quadruple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \the\t_syst_aux[][]}
+
+\def\syst_helpers_quadruple_empty_four_nop
+ {\fourthargumentfalse
+ \the\t_syst_aux[]}
+
+%D Quintuple:
+
+\unexpanded\def\doquintupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop}
+
+\def\syst_helpers_quintuple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop}
+
+\def\syst_helpers_quintuple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop}
+
+\def\syst_helpers_quintuple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop}
+
+\def\syst_helpers_quintuple_empty_four_yes[#1]%
+ {\fourthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop}
+
+\def\syst_helpers_quintuple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux[][][][][]}
+
+\def\syst_helpers_quintuple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux[][][][]}
+
+\def\syst_helpers_quintuple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux[][][]}
+
+\def\syst_helpers_quintuple_empty_four_nop
+ {\fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux[][]}
+
+\def\syst_helpers_quintuple_empty_five_nop
+ {\fifthargumentfalse
+ \the\t_syst_aux[]}
+
+%D Sixtuple:
+
+\unexpanded\def\dosixtupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop}
+
+\def\syst_helpers_sixtuple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop}
+
+\def\syst_helpers_sixtuple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop}
+
+\def\syst_helpers_sixtuple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop}
+
+\def\syst_helpers_sixtuple_empty_four_yes[#1]%
+ {\fourthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop}
+
+\def\syst_helpers_sixtuple_empty_five_yes[#1]%
+ {\fifthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop}
+
+\def\syst_helpers_sixtuple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \the\t_syst_aux[][][][][][]}
+
+\def\syst_helpers_sixtuple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \the\t_syst_aux[][][][][]}
+
+\def\syst_helpers_sixtuple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \the\t_syst_aux[][][][]}
+
+\def\syst_helpers_sixtuple_empty_four_nop
+ {\fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \the\t_syst_aux[][][]}
+
+\def\syst_helpers_sixtuple_empty_five_nop
+ {\fifthargumentfalse
+ \sixthargumentfalse
+ \the\t_syst_aux[][]}
+
+\def\syst_helpers_sixtuple_empty_six_nop
+ {\sixthargumentfalse
+ \the\t_syst_aux[]}
+
+%D Seventuple:
+
+\unexpanded\def\doseventupleempty#1%
+ {%syst_helpers_argument_reset
+ \t_syst_aux{#1}%
+ \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop}
+
+\def\syst_helpers_seventuple_empty_one_yes[#1]%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop}
+
+\def\syst_helpers_seventuple_empty_two_yes[#1]%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop}
+
+\def\syst_helpers_seventuple_empty_three_yes[#1]%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop}
+
+\def\syst_helpers_seventuple_empty_four_yes[#1]%
+ {\fourthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop}
+
+\def\syst_helpers_seventuple_empty_five_yes[#1]%
+ {\fifthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop}
+
+\def\syst_helpers_seventuple_empty_six_yes[#1]%
+ {\sixthargumenttrue
+ \toksapp\t_syst_aux{[{#1}]}%
+ \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop}
+
+\def\syst_helpers_seventuple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \the\t_syst_aux[][][][][][][]}
+
+\def\syst_helpers_seventuple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \the\t_syst_aux[][][][][][]}
+
+\def\syst_helpers_seventuple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \the\t_syst_aux[][][][][]}
+
+\def\syst_helpers_seventuple_empty_four_nop
+ {\fourthargumentfalse
+ \fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \the\t_syst_aux[][][][]}
+
+\def\syst_helpers_seventuple_empty_five_nop
+ {\fifthargumentfalse
+ \sixthargumentfalse
+ \seventhargumentfalse
+ \the\t_syst_aux[][][]}
+
+\def\syst_helpers_seventuple_empty_six_nop
+ {\sixthargumentfalse
+ \seventhargumentfalse
+ \the\t_syst_aux[][]}
+
+\def\syst_helpers_seventuple_empty_seven_nop
+ {\seventhargumentfalse
+ \the\t_syst_aux[]}
+
+%D Aliases:
+
+\let\dosingleargument \dosingleempty
+\let\dodoubleargument \dodoubleempty
+\let\dotripleargument \dotripleempty
+\let\doquadrupleargument \doquadrupleempty
+\let\doquintupleargument \doquintupleempty
+\let\dosixtupleargument \dosixtupleempty
+\let\doseventupleargument\doseventupleempty
+
+%D \macros
+%D {strippedcsname}
+%D
+%D The next macro can be very useful when using \type{\csname} like in:
+%D
+%D \starttyping
+%D \csname if\strippedcsname\something\endcsname
+%D \stoptyping
+%D
+%D This expands to \type{\ifsomething}.
+
+% \def\strippedcsname
+% {\expandafter\gobbleoneargument\string}
+
+\let\strippedcsname\csstring
+
+%D \macros
+%D {complexorsimple,complexorsimpleempty}
+%D
+%D Setups can be optional. A command expecting a setup is prefixed by \type
+%D {\complex}, a command without one gets the prefix \type {\simple}. Commands like
+%D this can be defined by:
+%D
+%D \starttyping
+%D \complexorsimple\command
+%D \stoptyping
+%D
+%D When \type{\command} is followed by a \type{[setup]}, then
+%D
+%D \starttyping
+%D \complexcommand [setup]
+%D \stoptyping
+%D
+%D executes, else we get
+%D
+%D \starttyping
+%D \simplecommand
+%D \stoptyping
+%D
+%D An alternative for \type{\complexorsimple} is:
+%D
+%D \starttyping
+%D \complexorsimpleempty {command}
+%D \stoptyping
+%D
+%D Depending on the presence of \type{[setup]}, this one leads to one of:
+%D
+%D \starttyping
+%D \complexcommando [setup]
+%D \complexcommando []
+%D \stoptyping
+%D
+%D Many \CONTEXT\ commands started as complex or simple ones, but changed into more
+%D versatile (more object oriented) ones using the \type {\get..argument} commands.
+
+\unexpanded\def\complexorsimple#1%
+ {% \relax % prevents lookahead, brrr
+ \doifelsenextoptional
+ {\firstargumenttrue \csname\s!complex\csstring#1\endcsname}
+ {\firstargumentfalse\csname\s!simple \csstring#1\endcsname}}
+
+\unexpanded\def\complexorsimpleempty#1%
+ {% \relax % prevents lookahead, brrr
+ \doifelsenextoptional
+ {\firstargumenttrue \csname\s!complex\csstring#1\endcsname}
+ {\firstargumentfalse\csname\s!complex\csstring#1\endcsname[]}}
+
+%D \macros
+%D {definecomplexorsimple,definecomplexorsimpleempty}
+%D
+%D The previous commands are used that often that we found it worthwile to offer two
+%D more alternatives. Watch the build in protection.
+
+\unexpanded\def\syst_helpers_complex_or_simple#1#2%
+ {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#2}}
+
+\unexpanded\def\syst_helpers_complex_or_simple_empty#1%
+ {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#1[]}}
+
+\unexpanded\def\definecomplexorsimple#1%
+ {\unexpanded\edef#1{\syst_helpers_complex_or_simple
+ \expandafter\noexpand\csname\s!complex\csstring#1\endcsname
+ \expandafter\noexpand\csname\s!simple \csstring#1\endcsname}}
+
+\unexpanded\def\definecomplexorsimpleempty#1%
+ {\unexpanded\edef#1{\syst_helpers_complex_or_simple_empty
+ \expandafter\noexpand\csname\s!complex\csstring#1\endcsname}}
+
+%D These commands are called as:
+%D
+%D \starttyping
+%D \definecomplexorsimple\command
+%D \stoptyping
+%D
+%D Of course, we must have available
+%D
+%D \starttyping
+%D \def\complexcommand[#1]{...}
+%D \def\simplecommand {...}
+%D \stoptyping
+%D
+%D Using this construction saves a few string now and then.
+
+%D \macros
+%D {dosinglegroupempty,dodoublegroupempty,dotriplegroupempty,
+%D doquadruplegroupempty, doquintuplegroupempty}
+%D
+%D We've already seen some commands that take care of
+%D optional arguments between \type{[]}. The next two commands
+%D handle the ones with \type{{}}. They are called as:
+%D
+%D \starttyping
+%D \dosinglegroupempty \ineedONEargument
+%D \dodoublegroupempty \ineedTWOarguments
+%D \dotriplegroupempty \ineedTHREEarguments
+%D \doquadruplegroupempty \ineedFOURarguments
+%D \doquintuplegroupempty \ineedFIVEarguments
+%D \stoptyping
+%D
+%D We can add additional definitions later when we have defined \type {\appendtoks}.
+
+\newconditional\c_syst_helpers_permit_spaces_between_groups
+
+\unexpanded\def \permitspacesbetweengroups{\settrue \c_syst_helpers_permit_spaces_between_groups}
+\unexpanded\def\dontpermitspacesbetweengroups{\setfalse\c_syst_helpers_permit_spaces_between_groups}
+
+\dontpermitspacesbetweengroups
+
+%D We can avoid the nasty if handling in \type {syst-gen} by splitting the lot in
+%D pieces so that we have no nested \type {\nextarguments} potentially being an
+%D \type {conditional} token. Okay, these macros are not called that often but it
+%D saves crap when tracing.
+
+\unexpanded\def\dosinglegroupempty#1%
+ {\t_syst_aux{#1}%
+ \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop}
+
+\def\syst_helpers_single_group_empty_one_nop
+ {\firstargumentfalse
+ \the\t_syst_aux{}}
+
+\unexpanded\def\dodoublegroupempty#1%
+ {\t_syst_aux{#1}%
+ \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop}
+
+\def\syst_helpers_group_double_empty_one_yes#1%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop}
+
+\def\syst_helpers_group_double_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \the\t_syst_aux{}{}}
+
+\def\syst_helpers_group_double_empty_two_nop
+ {\secondargumentfalse
+ \the\t_syst_aux{}}
+
+\unexpanded\def\dotriplegroupempty#1%
+ {\t_syst_aux{#1}%
+ \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop}
+
+\def\syst_helpers_group_triple_empty_one_yes#1%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop}
+
+\def\syst_helpers_group_triple_empty_two_yes#1%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop}
+
+\def\syst_helpers_group_triple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \the\t_syst_aux{}{}{}}
+
+\def\syst_helpers_group_triple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \the\t_syst_aux{}{}}
+
+\def\syst_helpers_group_triple_empty_three_nop
+ {\thirdargumentfalse
+ \the\t_syst_aux{}}
+
+\unexpanded\def\doquadruplegroupempty#1%
+ {\t_syst_aux{#1}%
+ \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop}
+
+\def\syst_helpers_group_quadruple_empty_one_yes#1%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop}
+
+\def\syst_helpers_group_quadruple_empty_two_yes#1%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop}
+
+\def\syst_helpers_group_quadruple_empty_three_yes#1%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop}
+
+\def\syst_helpers_group_quadruple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \the\t_syst_aux{}{}{}{}}
+
+\def\syst_helpers_group_quadruple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \the\t_syst_aux{}{}{}}
+
+\def\syst_helpers_group_quadruple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \the\t_syst_aux{}{}}
+
+\def\syst_helpers_group_quadruple_empty_four_nop
+ {\fourthargumentfalse
+ \the\t_syst_aux{}}
+
+\unexpanded\def\doquintuplegroupempty#1%
+ {\t_syst_aux{#1}%
+ \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop}
+
+\def\syst_helpers_group_quintuple_empty_one_yes#1%
+ {\firstargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop}
+
+\def\syst_helpers_group_quintuple_empty_two_yes#1%
+ {\secondargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop}
+
+\def\syst_helpers_group_quintuple_empty_three_yes#1%
+ {\thirdargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop}
+
+\def\syst_helpers_group_quintuple_empty_four_yes#1%
+ {\fourthargumenttrue
+ \toksapp\t_syst_aux{{#1}}%
+ \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop}
+
+\def\syst_helpers_group_quintuple_empty_one_nop
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux{}{}{}{}{}}
+
+\def\syst_helpers_group_quintuple_empty_two_nop
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux{}{}{}{}}
+
+\def\syst_helpers_group_quintuple_empty_three_nop
+ {\thirdargumentfalse
+ \fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux{}{}{}}
+
+\def\syst_helpers_group_quintuple_empty_four_nop
+ {\fourthargumentfalse
+ \fifthargumentfalse
+ \the\t_syst_aux{}{}}
+
+\def\syst_helpers_group_quintuple_empty_five_nop
+ {\fifthargumentfalse
+ \the\t_syst_aux{}}
+
+%D These macros can explictly take care of spaces, which means that the next
+%D definition and calls are valid:
+%D
+%D \starttyping
+%D \def\test#1#2#3{[#1#2#3]}
+%D
+%D \dotriplegroupempty\test {a}{b}{c}
+%D \dotriplegroupempty\test {a}{b}
+%D \dotriplegroupempty\test {a}
+%D \dotriplegroupempty\test
+%D \dotriplegroupempty\test {a} {b} {c}
+%D \dotriplegroupempty\test {a} {b}
+%D \dotriplegroupempty\test
+%D {a}
+%D {b}
+%D \stoptyping
+%D
+%D And alike.
+
+%D \macros
+%D {firstofoneargument, firstoftwoarguments, firstofthreearguments
+%D secondoftwoarguments, secondofthreearguments,
+%D thirdofthreearguments}
+%D
+%D The next six macros (dedicated to Taco) can conveniently used to select
+%D arguments. Their names explain their functionality.
+
+\def\firstofoneargument #1{#1}
+
+\def\firstoftwoarguments #1#2{#1}
+\def\secondoftwoarguments #1#2{#2}
+
+\def\firstofthreearguments #1#2#3{#1}
+\def\secondofthreearguments #1#2#3{#2}
+\def\thirdofthreearguments #1#2#3{#3}
+
+\def\firstoffourarguments #1#2#3#4{#1}
+\def\secondoffourarguments #1#2#3#4{#2}
+\def\thirdoffourarguments #1#2#3#4{#3}
+\def\fourthoffourarguments #1#2#3#4{#4}
+
+\def\firstoffivearguments #1#2#3#4#5{#1}
+\def\secondoffivearguments #1#2#3#4#5{#2}
+\def\thirdoffivearguments #1#2#3#4#5{#3}
+\def\fourthoffivearguments #1#2#3#4#5{#4}
+\def\fifthoffivearguments #1#2#3#4#5{#5}
+
+\def\firstofsixarguments #1#2#3#4#5#6{#1}
+\def\secondofsixarguments#1#2#3#4#5#6{#2}
+\def\thirdofsixarguments #1#2#3#4#5#6{#3}
+\def\fourthofsixarguments#1#2#3#4#5#6{#4}
+\def\fifthofsixarguments #1#2#3#4#5#6{#5}
+\def\sixthofsixarguments #1#2#3#4#5#6{#6}
+
+\unexpanded\def\firstofoneunexpanded #1{#1}
+
+\unexpanded\def\firstoftwounexpanded #1#2{#1}
+\unexpanded\def\secondoftwounexpanded #1#2{#2}
+
+\unexpanded\def\firstofthreeunexpanded #1#2#3{#1}
+\unexpanded\def\secondofthreeunexpanded#1#2#3{#2}
+\unexpanded\def\thirdofthreeunexpanded #1#2#3{#3}
+
+%D \macros
+%D {globalletempty,letempty,
+%D letvalueempty,letgvalueempty,
+%D letvaluerelax,letgvaluerelax}
+%D
+%D Trivial:
+
+\unexpanded\def\letempty #1{\let #1\empty}
+\unexpanded\def\globalletempty#1{\glet#1\empty}
+
+\unexpanded\def\letvalueempty #1{\expandafter\let \csname#1\endcsname\empty}
+\unexpanded\def\letgvalueempty#1{\expandafter\glet\csname#1\endcsname\empty}
+\unexpanded\def\letvaluerelax #1{\expandafter\let \csname#1\endcsname\relax}
+\unexpanded\def\letgvalurelax #1{\expandafter\glet\csname#1\endcsname\relax}
+
+\unexpanded\def\relaxvalueifundefined#1%
+ {\ifcsname#1\endcsname \else
+ \expandafter\let\csname#1\endcsname\relax
+ \fi}
+
+%D \macros
+%D {wait}
+%D
+%D The next macro hardly needs explanation. Because no nesting is to be expected, we
+%D can reuse \type {\wait} within \type {\wait} itself.
+
+\unexpanded\def\wait
+ {\begingroup
+ \read16 to \wait
+ \endgroup}
+
+%D \macros
+%D {writestring,writeline,
+%D writestatus,statuswidth,normalwritestatus}
+%D
+%D Maybe one didn't notice, but we've already introduced a macro for showing
+%D messages. In the multi||lingual modules, we will also introduce a mechanism for
+%D message passing. For the moment we stick to the core macros:
+%D
+%D \starttyping
+%D \writestring {string}
+%D \writeline
+%D \writestatus {category} {message}
+%D \stoptyping
+%D
+%D Messages are formatted. One can provide the maximum with of the identification
+%D string with the macro \type {\statuswidth}.
+
+\setnewconstant\statuswidth 15
+\setnewconstant\statuswrite 128 % \pluscxxviii
+
+\ifdefined\writestring \else
+
+ \unexpanded\def\writestring{\immediate\write\statuswrite}
+ \unexpanded\def\writeline {\writestring{}}
+
+\fi
+
+\unexpanded\def\normalwritestatus#1#2%
+ {\writestring{\expandafter\syst_helpers_split_status_yes\expandafter\statuswidth#1%
+ \space\space\space\space\space\space\space
+ \space\space\space\space\space\space\space
+ \space\space\space\space\space\space\end
+ \space:\space#2}}
+
+\def\syst_helpers_split_status_yes#1#2%
+ {\ifcase#1 \expandafter\syst_helpers_split_status_nop\fi#2%
+ \expandafter\syst_helpers_split_status_yes\expandafter{\the\numexpr#1+\minusone\relax}}
+
+\def\syst_helpers_split_status_nop#1\end
+ {}
+
+%D \macros
+%D {immediatemessage}
+%D
+%D A fully expandable message:
+
+\let\immediatemessage\clf_immediatemessage % {} mandate
+
+%D \macros
+%D {rawgetparameters}
+%D
+%D A raw and dirty alternative for \type {\getparameters}; no checking is done!
+
+\unexpanded\def\rawsetparameter#1=#2,%
+ {\if]#1\else
+ \expandafter\def\csname\rawparameterprefix#1\endcsname{#2}%
+ \expandafter\rawsetparameter
+ \fi}
+
+\unexpanded\def\rawgetparameters[#1][#2% some 5-10% faster
+ {\ifx#2]% test is needed, else bomb on [#1][]
+ \expandafter\gobbleoneargument
+ \else
+ \def\rawparameterprefix{#1}%
+ \expandafter\dorawgetparameters
+ \fi#2}
+
+\def\dorawgetparameters#1]%
+ {\expandafter\rawsetparameter#1,]=,}
+
+%D \macros
+%D {doglobal,
+%D redoglobal,dodoglobal,resetglobal}
+%D
+%D The two macros \type {\redoglobal} and \type{\dodoglobal} are used in this and
+%D some other modules to enforce a user specified \type {\doglobal} action. The last
+%D and often only global assignment in a macro is done with \type {\dodoglobal}, but
+%D all preceding ones with \type {\redoglobal}. When using only alternatives, one
+%D can reset this mechanism with \type {\resetglobal}.
+
+\unexpanded\def\resetglobal
+ {\let\redoglobal\relax
+ \let\dodoglobal\relax}
+
+\resetglobal
+
+\unexpanded\def\doglobal
+ {\ifx\redoglobal\relax
+ \let\redoglobal\global
+ \let\dodoglobal\syst_helpers_dodo_global
+ \fi}
+
+\def\syst_helpers_dodo_global
+ {\resetglobal\global}
+
+\def\saveglobal
+ {\let\syst_helpers_dodo_global\dodoglobal
+ \let\syst_helpers_redo_global\redoglobal}
+
+\def\restoreglobal
+ {\let\redoglobal\syst_helpers_redo_global
+ \let\dodoglobal\syst_helpers_dodo_global}
+
+%D A very useful application of this macro is \type {\newif}, \TEX's fake boolean
+%D type. Not being a primitive, \type {\global} hopelessly fails here. But a slight
+%D adaption of Knuth's original macro permits:
+%D
+%D \starttyping
+%D \doglobal\newif\iftest
+%D \stoptyping
+%D
+%D Of course one can still say:
+%D
+%D \starttyping
+%D \global\testtrue
+%D \global\testfalse
+%D \stoptyping
+%D
+%D Apart from the prefixes, a few more \type {\expandafters} are needed:
+
+% \unexpanded\def\newif#1% uses the original plain \@if
+% {\privatescratchcounter\escapechar
+% \escapechar\minusone
+% \expandafter\expandafter\expandafter
+% \redoglobal\expandafter\expandafter\expandafter
+% \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}%
+% \expandafter\expandafter\expandafter
+% \redoglobal\expandafter\expandafter\expandafter
+% \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}%
+% \dodoglobal\@if#1{false}%
+% \escapechar\privatescratchcounter}
+
+\normalprotected\def\newif#1% see syst-ini.mkiv
+ {\let\new_if_saved\newif
+ \let\newif\new_if_check
+ \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
+ \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
+ \dodoglobal\csname\expandafter\newif\csstring#1false\endcsname
+ \let\newif\new_if_saved}
+
+%D Also new:
+
+\unexpanded\def\define#1%
+ {\ifdefined#1%
+ \message{[\noexpand#1is already defined]}%
+ \unexpanded\expandafter\def\expandafter\gobbleddefinition
+ \else
+ \unexpanded\expandafter\def
+ \fi#1}
+
+\unexpanded\def\redefine#1%
+ {\ifdefined#1%
+ \message{[\noexpand#1is redefined]}%
+ \fi
+ \unexpanded\def#1}
+
+\unexpanded\def\definemacro#1%
+ {\ifdefined#1%
+ \message{[\noexpand#1is already defined]}%
+ \unexpanded\expandafter\def\expandafter\gobbleddefinition
+ \else
+ \unexpanded\expandafter\def
+ \fi#1}
+
+% \define\hans{hans}
+% \redefine\hans{hans}
+% \define\hans#1[]#2#3{hans}
+
+%D The next variant fits nicely in the setups syntax:
+%D
+%D \starttyping
+%D \starttexdefinition bagger [#1] #2
+%D oeps
+%D #1
+%D oeps
+%D \stoptexdefinition
+%D
+%D \bagger [a] {b}
+%D \stoptyping
+
+% \starttexdefinition test
+% oeps
+% \stoptexdefinition
+%
+% [\test]
+
+\def\s!unexpanded{unexpanded}
+
+\bgroup \obeylines
+
+\glet\stoptexdefinition\relax
+
+\unexpanded\gdef\starttexdefinition%
+ {\bgroup%
+ \obeylines%
+ \syst_helpers_start_tex_definition}
+
+\gdef\syst_helpers_start_tex_definition#1
+ {\catcode\endoflineasciicode\ignorecatcode%
+ \clf_texdefinition_one{#1}}
+
+\gdef\dostarttexdefinition#1\stoptexdefinition%
+ {\egroup%
+ \clf_texdefinition_two{#1}}
+
+\egroup
+
+% \unexpanded\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace
+
+\unexpanded\def\texdefinition#1{\begincsname#1\endcsname}
+
+% This is a first variant, more might be added:
+
+\unexpanded\def\starttexcode{\unprotect}
+\unexpanded\def\stoptexcode {\protect}
+
+%D \macros
+%D {newcounter,
+%D increment,decrement}
+%D
+%D Unfortunately the number of \COUNTERS\ in \TEX\ is limited, but fortunately we
+%D can store numbers in a macro. We can increment such pseudo \COUNTERS\ with \type
+%D {\increment}.
+%D
+%D \starttyping
+%D \increment(\counter,20)
+%D \increment(\counter,-4)
+%D \increment(\counter)
+%D \increment\counter
+%D \stoptyping
+%D
+%D After this sequence of commands, the value of \type {\counter} is 20, 16, 17
+%D and~18. Of course there is also the complementary command \type {\decrement}.
+%D
+%D Global assignments are possible too, using \type{\doglobal}:
+%D
+%D \starttyping
+%D \doglobal\increment\counter
+%D \stoptyping
+%D
+%D When \type {\counter} is undefined, it's value is initialized at~0. It is
+%D nevertheless better to define a \COUNTER\ explicitly. One reason could be that
+%D the \COUNTER\ can be part of a test with \type {\ifnum} and this conditional does
+%D not accept undefined macro's. The \COUNTER\ in our example can for instance be
+%D defined with:
+%D
+%D \starttyping
+%D \newcounter\counter
+%D \stoptyping
+%D
+%D The command \type {\newcounter} must not be confused with \type {\newcount}! Of
+%D course this mechanism is much slower than using \TEX's \COUNTERS\ directly. In
+%D practice \COUNTERS\ (and therefore our pseudo counters too) are seldom the
+%D bottleneck in the processing of a text. Apart from some other incompatilities we
+%D want to mention a pitfal when using \type {\ifnum}.
+%D
+%D \starttyping
+%D \ifnum\normalcounter=\pseudocounter \doif \else \doelse \fi
+%D \ifnum\pseudocounter=\normalcounter \doif \else \doelse \fi
+%D \stoptyping
+%D
+%D In the first test, \TEX\ continues it's search for the second number after
+%D reading \type {\pseudocounter}, while in the second test, it stops reading after
+%D having encountered a real one. Tests like the first one therefore can give
+%D unexpected results, for instance execution of \type {\doif} even if both numbers
+%D are unequal.
+
+\def\zerocountervalue{0}
+
+\unexpanded\def\newcounter#1%
+ {\dodoglobal\let#1\zerocountervalue}
+
+%D Nowadays we don't mind a few more tokens if we can gain a bit of speed.
+
+\def\syst_helpers_do_increment#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\plusone \relax}}
+\def\syst_helpers_do_decrement#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\minusone\relax}}
+
+\def\syst_helpers_do_do_do_increment#1,#2){\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+#2\relax}}
+\def\syst_helpers_do_do_do_decrement#1,#2){\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi-#2\relax}}
+
+\def\syst_helpers_do_do_increment(#1%
+ {\def\m_syst_action_yes{\syst_helpers_do_do_do_increment#1}%
+ \def\m_syst_action_nop{\syst_helpers_do_do_do_increment#1,\plusone}%
+ \doifelsenextcharcs,\m_syst_action_yes\m_syst_action_nop}
+
+\def\syst_helpers_do_do_decrement(#1%
+ {\def\m_syst_action_yes{\syst_helpers_do_do_do_decrement#1}%
+ \def\m_syst_action_nop{\syst_helpers_do_do_do_decrement#1,\plusone}%
+ \doifelsenextcharcs,\m_syst_action_yes\m_syst_action_nop}
+
+\unexpanded\def\increment{\doifelsenextcharcs(\syst_helpers_do_do_increment\syst_helpers_do_increment}
+\unexpanded\def\decrement{\doifelsenextcharcs(\syst_helpers_do_do_decrement\syst_helpers_do_decrement}
+
+\unexpanded\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}}
+\unexpanded\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}}
+
+\unexpanded\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname}
+\unexpanded\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname}
+
+%D \macros
+%D {newsignal}
+%D
+%D When writing advanced macros, we cannot do without signaling. A signal is a small
+%D (invisible) kern or penalty that signals the next macro that something just
+%D happened. This macro can take any action depending on the previous signal.
+%D Signals must be unique and the next macro takes care of that.
+%D
+%D \starttyping
+%D \newsignal\somesignal
+%D \stoptyping
+%D
+%D Signals old dimensions and can be used in skips, kerns and tests like \type
+%D {\ifdim}.
+
+\newdimen\maximumsignal % step is about 0.00025pt
+
+\unexpanded\def\newsignal#1%
+ {\ifdefined#1\else
+ \advance\maximumsignal 2\scaledpoint % to be save in rounding
+ \edef#1{\the\maximumsignal}%
+ \fi}
+
+%D \macros
+%D {strippedcsname}
+%D
+%D The next macro can be very useful when using \type {\csname} like in:
+%D
+%D \starttyping
+%D \csname if\strippedcsname\something\endcsname
+%D \stoptyping
+
+\let\checkedstrippedcsname\csstring
+
+%D \macros
+%D {savenormalmeaning}
+%D
+%D We will use this one in:
+
+\unexpanded\def\savenormalmeaning#1%
+ {\ifcsname normal\csstring#1\endcsname \else
+ \expandafter\let\csname normal\csstring#1\endcsname#1%
+ \fi}
+
+%D \macros
+%D {dorecurse,recurselevel,recursedepth,
+%D dostepwiserecurse}
+%D
+%D \TEX\ does not offer us powerfull for||loop mechanisms. On the other hand its
+%D recursion engine is quite unique. We therefore identify the for||looping macros
+%D by this method. The most simple alternative is the one that only needs a number.
+%D
+%D \starttyping
+%D \dorecurse {n} {whatever we want}
+%D \stoptyping
+%D
+%D This macro can be nested without problems and therefore be used in situations
+%D where \PLAIN\ \TEX's \type {\loop} macro ungracefully fails. The current value of
+%D the counter is available in \type {\recurselevel}, before as well as after the
+%D \typ {whatever we wat} stuff.
+%D
+%D \starttyping
+%D \dorecurse % inner loop
+%D {10}
+%D {\recurselevel: % outer value
+%D \dorecurse % inner loop
+%D {\recurselevel} % outer value
+%D {\recurselevel} % inner value
+%D \dorecurse % inner loop
+%D {\recurselevel} % outer value
+%D {\recurselevel} % inner value
+%D \endgraf}
+%D \stoptyping
+%D
+%D In this example the first, second and fourth \type {\recurselevel} concern the
+%D outer loop, while the third and fifth one concern the inner loop. The depth of
+%D the nesting is available for inspection in \type {\recursedepth}.
+%D
+%D Both \type {\recurselevel} and \type {\recursedepth} are macros. The real
+%D \COUNTERS\ are hidden from the user because we don't want any interference.
+
+\newcount\outerrecurse
+\newcount\innerrecurse
+
+\def\recursedepth{\the\outerrecurse}
+\def\recurselevel{0}
+
+\let\syst_helpers_stepwise_next\relax
+
+\installsystemnamespace{recurseindex}
+\installsystemnamespace{recurseaction}
+
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+ {\global\advance\outerrecurse \plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#4}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+ \ifnum#3>\zerocount\relax
+ \ifnum#2<#1\relax
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
+ \else
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse
+ \fi
+ \orelse\ifnum#3<\zerocount\relax
+ \ifnum#1<#2\relax
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
+ \else
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse
+ \fi
+ \else
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
+ \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}}
+
+\unexpanded\def\syst_helpers_stepwise_recurse#1#2#3% from to step
+ {\ifnum#1>#2\relax
+ \expandafter\syst_helpers_stepwise_recurse_nop
+ \else
+ \def\recurselevel{#1}%
+ \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter
+ \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
+
+\unexpanded\def\syst_helpers_recurse_content
+ {\csname\??recurseaction\the\outerrecurse\endcsname}
+
+\unexpanded\def\syst_helpers_stepwise_recurse_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_stepwise_recurse}
+
+\unexpanded\def\syst_helpers_stepwise_reverse#1#2#3% from to step
+ {\ifnum#1<#2\relax
+ \expandafter\syst_helpers_stepwise_recurse_nop
+ \else
+ \def\recurselevel{#1}%
+ \innerrecurse#1\relax
+ \advance\innerrecurse#3\relax
+ \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter
+ \fi\expandafter{\the\innerrecurse}{#2}{#3}}
+
+\unexpanded\def\syst_helpers_stepwise_reverse_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_stepwise_reverse}
+
+\unexpanded\def\syst_helpers_stepwise_exit
+ {\syst_helpers_stepwise_recurse_nop\relax}
+
+\unexpanded\def\syst_helpers_stepwise_recurse_nop#1#2#3#4%
+ {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
+ \global\advance\outerrecurse\minusone}
+
+\unexpanded\def\dorecurse#1%
+ {\dostepwiserecurse\plusone{#1}\plusone}
+
+\def\doexpandedrecurse#1#2% user macro (also was \doxprecurse)
+ {\ifnum#1>\zerocount
+ #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-\plusone\relax}{#2}%
+ \fi}
+
+%D As we can see here, the simple command \type{\dorecurse} is a special case of the
+%D more general:
+%D
+%D \starttyping
+%D \dostepwiserecurse {from} {to} {step} {action}
+%D \stoptyping
+%D
+%D This commands accepts positive and negative steps. Illegal values are handles as
+%D good as possible and the macro accepts numbers and \COUNTERS.
+%D
+%D \starttyping
+%D \dostepwiserecurse {1} {10} {2} {...}
+%D \dostepwiserecurse {10} {1} {-2} {...}
+%D \stoptyping
+%D
+%D Because the simple case is used often, we implement it more efficiently:
+
+\unexpanded\def\dorecurse#1%
+ {\ifcase#1\relax
+ \expandafter\gobbletwoarguments
+ \or
+ \expandafter\syst_helpers_recurse_y
+ \else
+ \expandafter\syst_helpers_recurse_x
+ \fi{#1}}
+
+\unexpanded\def\syst_helpers_recurse_x#1#2%
+ {\global\advance\outerrecurse \plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#2}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+ \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}}
+
+\unexpanded\def\syst_helpers_recurse_y#1#2%
+ {\global\advance\outerrecurse \plusone
+ \expandafter\glet\csname\??recurseindex\the\outerrecurse\endcsname\recurselevel
+ \let\recurselevel\!!plusone
+ #2%
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
+ \global\advance\outerrecurse \minusone}
+
+\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to
+ {\ifnum#1>#2\relax
+ \expandafter\syst_helpers_recurse_indeed_nop
+ \else
+ \def\recurselevel{#1}%
+ \doubleexpandafter\syst_helpers_recurse_indeed_yes
+ \fi\expandafter{\the\numexpr\recurselevel+\plusone\relax}{#2}}
+
+\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to
+ {\ifnum#1>#2\relax
+ \expandafter\syst_helpers_recurse_indeed_nop
+ \else
+ \def\recurselevel{#1}%
+ \innerrecurse#1\advance\innerrecurse\plusone
+ \doubleexpandafter\syst_helpers_recurse_indeed_yes
+ \fi\expandafter{\the\innerrecurse}{#2}}
+
+\unexpanded\def\syst_helpers_recurse_indeed_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_recurse_indeed}
+
+\unexpanded\def\syst_helpers_recurse_indeed_nop#1#2#3%
+ {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
+ \global\advance\outerrecurse \minusone }
+
+%D \macros
+%D {dowith}
+%D
+%D Here's a loop over whatever is in a list:
+%D
+%D \starttyping
+%D \dowith{a,b,c}{[#1]}
+%D \stoptyping
+
+\unexpanded\def\dowith#1#2%
+ {\def\syst_helpers_with##1{#2}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_with}
+
+%D \macros
+%D {doloop,exitloop}
+%D
+%D Sometimes loops are not determined by counters, but by (a combinations of)
+%D conditions. We therefore implement a straightforward loop, which can only be left
+%D when we explictly exit it. Nesting is supported. First we present a more
+%D extensive alternative.
+%D
+%D \starttyping
+%D \doloop
+%D {Some kind of typesetting punishment \par
+%D \ifnum\pageno>100 \exitloop \fi}
+%D \stoptyping
+%D
+%D When needed, one can call for \type {\looplevel} and \type {\loopdepth}.
+
+\let\endofloop\donothing % maybe \syst_helpers_loop_end
+
+\unexpanded\def\doloop#1%
+ {\global\advance\outerrecurse \plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#1}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+ \let\endofloop\syst_helpers_loop
+ \syst_helpers_loop1} % no \plusone else \recurselevel wrong
+
+\unexpanded\def\syst_helpers_loop#1%
+ {\def\recurselevel{#1}%
+ \expandafter\syst_helpers_loop_yes\expandafter{\the\numexpr\recurselevel+\plusone\relax}}
+
+\unexpanded\def\syst_helpers_loop_yes
+ {\syst_helpers_recurse_content
+ \endofloop}
+
+\unexpanded\def\syst_helpers_loop_nop#1%
+ {\let\endofloop\syst_helpers_loop % new, permits nested \doloop's
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
+ \global\advance\outerrecurse\minusone}
+
+\unexpanded\def\exitloop % \exitloop quits at end
+ {\let\endofloop\syst_helpers_loop_nop}
+
+\unexpanded\def\exitloopnow#1\endofloop % \exitloopnow quits directly
+ {\syst_helpers_loop_nop}
+
+%D The loop is executed at least once, so beware of situations
+%D like:
+%D
+%D \starttyping
+%D \doloop {\exitloop some commands}
+%D \stoptyping
+%D
+%D It's just a matter of putting the text into the \type {\if} statement that should
+%D be there anyway, like in:
+%D
+%D \starttyping
+%D \doloop {\ifwhatever \exitloop \else some commands\fi}
+%D \stoptyping
+%D
+%D You can also quit a loop immediately, by using \type
+%D {\exitloopnow} instead. Beware, this is more sensitive
+%D for conditional errors.
+
+%D Krzysztof Leszczynski suggested to provide access to the level by means of a
+%D \type {#1}. I decided to pass the more frequently used level as \type {#1} and
+%D the less favoured depth as \type {#2}. The intended usage is:
+%D
+%D \starttyping
+%D \dorecurse{3}{\definesymbol[test-#1][xx-#1]}
+%D
+%D \def\test{\dorecurse{3}{\definesymbol[test-##1][xx-##1]}} \test
+%D
+%D \symbol[test-1]\quad\symbol[test-2]\quad\symbol[test-3]
+%D \stoptyping
+%D
+%D Since the hashed arguments are expanded, we don't need tricky expansion here.
+%D
+%D \starttyping
+%D \dorecurse{3}{\expanded{\definesymbol[test-\recurselevel][xx-\recurselevel]}}
+%D \stoptyping
+
+\def\syst_helpers_recurse_content
+ {\csname\??recurseaction\the\outerrecurse\expandafter\expandafter\expandafter\endcsname
+ \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\the\outerrecurse}}
+
+\unexpanded\def\syst_helpers_recurse_x#1#2%
+ {\global\advance\outerrecurse \plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#2}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+ \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}}
+
+\unexpanded\def\syst_helpers_recurse_y#1#2%
+ {\global\advance\outerrecurse \plusone
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+ \let\recurselevel\!!plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#2}%
+ \syst_helpers_recurse_content
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
+ \global\advance\outerrecurse \minusone}
+
+\unexpanded\def\doloop#1%
+ {\global\advance\outerrecurse \plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#1}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+ \let\endofloop\syst_helpers_loop
+ \syst_helpers_loop1} % no \plusone else \recurselevel wrong
+
+\installsystemnamespace{recursestepwise}
+
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+ {\global\advance\outerrecurse \plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+ \csname\??recursestepwise
+ % we need the x in order to avoid the \relax that tex adds
+ \ifnum#3>\zerocount
+ \ifnum#2<#1x\else d\fi
+ \orelse\ifnum#3<\zerocount
+ \ifnum#1<#2x\else r\fi
+ \fi
+ \expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}}
+ % \expandafter\endcsname\expandafter{\number#1\expandafter}\expandafter{\number#2\expandafter}\expandafter{\number#3}}
+
+\letvalue{\??recursestepwise x}\syst_helpers_stepwise_exit
+\letvalue{\??recursestepwise d}\syst_helpers_stepwise_recurse
+\letvalue{\??recursestepwise r}\syst_helpers_stepwise_reverse
+
+\newcount\fastloopindex
+\newcount\fastloopfinal
+
+\let\m_syst_helpers_fast_loop_cs\relax
+
+\unexpanded\def\dofastloopcs#1%
+ {\fastloopfinal#1\relax
+ \ifcase\fastloopfinal
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\syst_helpers_fast_loop_cs
+ \fi}
+
+\unexpanded\def\syst_helpers_fast_loop_cs#1%
+ {\let\m_syst_helpers_fast_loop_cs#1%
+ \fastloopindex\plusone
+ \syst_helpers_fast_loop_cs_step}
+
+\unexpanded\def\syst_helpers_fast_loop_cs_step
+ {\ifnum\fastloopindex>\fastloopfinal
+ \let\m_syst_helpers_fast_loop_cs\relax
+ \else
+ \m_syst_helpers_fast_loop_cs
+ \advance\fastloopindex\plusone
+ \expandafter\syst_helpers_fast_loop_cs_step
+ \fi}
+
+% Helper:
+
+\unexpanded\def\resetrecurselevel{\let\recurselevel\!!zerocount}
+
+\let\recurselevel\!!zerocount
+
+% \appendtoks \resetrecurselevel \to \everydump
+
+%D \macros
+%D {doloopoverlist}
+%D
+%D \starttyping
+%D \doloopoverlist {red,green,blue} {
+%D \setuppalet[\recursestring]
+%D \doloopoverlist {light,normal,dark} {
+%D \blackrule[color=\recursestring,width=20cm,height=2cm,depth=0cm]\par
+%D }
+%D }
+%D \stoptyping
+%D
+%D or:
+%D
+%D \starttyping
+%D \doloopoverlist {red,green,blue} {
+%D \setuppalet[#1]
+%D \doloopoverlist {light,normal,dark} {
+%D \blackrule[color=##1,width=20cm,height=2cm,depth=0cm]\par
+%D }
+%D }
+%D \stoptyping
+
+\unexpanded\def\doloopoverlist#1#2%
+ {\global\advance\outerrecurse\plusone
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1{\edef\recursestring{##1}#2}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recursestring
+ \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\??recurseaction\the\outerrecurse\endcsname}}%
+ \expandafter\let\expandafter\recursestring\csname\??recurseindex\the\outerrecurse\endcsname
+ \global\advance\outerrecurse\minusone}
+
+%D \macros
+%D {newevery,everyline,EveryLine,EveryPar}
+%D
+%D Lets skip to something quite different. It's common use to use \type {\everypar}
+%D for special purposes. In \CONTEXT\ we use this primitive for locating sidefloats.
+%D This means that when user assignments to \type {\everypar} can interfere with
+%D those of the package. We therefore introduce \type {\EveryPar}.
+%D
+%D The same goes for \type {\EveryLine}. Because \TEX\ offers no \type {\everyline}
+%D primitive, we have to call for \type {\everyline} when we are working on a line
+%D by line basis. Just by calling \type {\EveryPar{}} and \type {\EveryLine{}} we
+%D restore the old situation.
+
+% \dorecurse{2}{
+% \expanded{\everypar{before \recurselevel\space}}
+% \EveryPar{x } [before \recurselevel\space x] \par
+% \EveryPar{y } [before \recurselevel\space y] \par
+% \EveryPar{} [before \recurselevel] \par
+% \EveryPar{x } \EveryPar{y } \EveryPar{} [before \recurselevel] \par
+% \EveryPar{y } \everypar{before } [before] \par
+% }
+
+\installsystemnamespace{extraevery}
+
+\unexpanded\def\newevery#1#2%
+ {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere
+ \ifx#2\relax\orelse\ifdefined#2\else
+ \expandafter\newtoks\csname\??extraevery\csstring#1\endcsname
+ \edef#2{\syst_helpers_every#1\csname\??extraevery\csstring#1\endcsname}%
+ \fi}
+
+\unexpanded\def\syst_helpers_every#1#2%
+ {\removetoks\the#2\from#1%
+ \appendtoks\the#2\to #1%
+ #2}
+
+%D This one permits definitions like:
+
+\newevery \everypar \EveryPar % we get a warning which is ok
+\newevery \everyline \EveryLine
+
+%D and how about:
+
+\newtoks \neverypar
+
+\unexpanded\def\forgeteverypar
+ {\everypar{\the\neverypar}}
+
+%D Which we're going to use indeed! When the second argument equals \type {\relax},
+%D the first token list is created unless it is already defined.
+%D
+%D Technically spoken we could have used the method we are going to present in the
+%D visual debugger. First we save the primitive \type{\everypar}:
+%D
+%D \starttyping
+%D \let\normaleverypar=\everypar
+%D \stoptyping
+%D
+%D Next we allocate a \TOKENLIST\ named \type{\everypar}, which means that
+%D \type{\everypar} is no longer a primitive but something like \type{\toks44}.
+%D
+%D \starttyping
+%D \newtoks\everypar
+%D \stoptyping
+%D
+%D Because \TEX\ now executes \type{\normaleverypar} instead of \type{\everypar}, we
+%D are ready to assign some tokens to this internally known and used \TOKENLIST.
+%D
+%D \starttyping
+%D \normaleverypar={all the things the system wants to do \the\everypar}
+%D \stoptyping
+%D
+%D Where the user can provide his own tokens to be expanded every time he expects
+%D them to expand.
+%D
+%D \starttyping
+%D \everypar={something the user wants to do}
+%D \stoptyping
+%D
+%D We don't use this method because it undoubtly leads to confusing situations,
+%D especially when other packages are used, but it's this kind of tricks that make
+%D \TEX\ so powerful.
+
+%D \macros
+%D {convertargument,convertcommand,convertvalue}
+%D
+%D Some persistent experimenting led us to the next macro. This macro converts a
+%D parameter or an expanded macro to it's textual meaning.
+%D
+%D \starttyping
+%D \convertargument ... \to \command
+%D \stoptyping
+%D
+%D For example,
+%D
+%D \starttyping
+%D \convertargument{one \two \three{four}}\to\ascii
+%D \stoptyping
+%D
+%D The resulting macro \type{\ascii} can be written to a file or the terminal
+%D without problems. In \CONTEXT\ we use this macro for generating registers and
+%D tables of contents.
+%D
+%D The second conversion alternative accepts a command:
+%D
+%D \starttyping
+%D \convertcommand\command\to\ascii
+%D \stoptyping
+%D
+%D Both commands accept the prefix \type{\doglobal} for global assignments.
+
+\unexpanded\def\convertvalue#1\to
+ {\expandafter\convertcommand\csname#1\endcsname\to}
+
+\unexpanded\def\defconvertedvalue#1#2% less sensitive for \to
+ {\expandafter\defconvertedcommand\expandafter#1\csname#2\endcsname}
+
+%D \macros
+%D {doifassignmentelse}
+%D
+%D A lot of \CONTEXT\ commands take optional arguments, for instance:
+%D
+%D \starttyping
+%D \dothisorthat[alfa,beta]
+%D \dothisorthat[first=foo,second=bar]
+%D \dothisorthat[alfa,beta][first=foo,second=bar]
+%D \stoptyping
+%D
+%D Although a combined solution is possible, we prefer a seperation. The next
+%D command takes care of propper handling of such multi||faced commands.
+%D
+%D \starttyping
+%D \doifassignmentelse {...} {then ...} {else ...}
+%D \stoptyping
+
+\def\syst_helpers_check_if_assignment_else#1=#2#3^^^^0004{\if#2^^^^0003}%
+\def\syst_helpers_check_else_assignment_if#1=#2#3^^^^0004{\unless\if#2^^^^0003}%
+
+\unexpanded\def\doifelseassignment#1%
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=^^^^0003^^^^0003^^^^0004%
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\unexpanded\def\doifelseassignmentcs#1#2#3%
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=^^^^0003^^^^0003^^^^0004%
+ \expandafter#3%
+ \else
+ \expandafter#2%
+ \fi}
+
+\let\doifassignmentelse \doifelseassignment
+\let\doifassignmentelsecs\doifelseassignmentcs
+
+\newif\ifassignment
+
+\unexpanded\def\docheckassignment#1%
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=^^^^0003^^^^0003^^^^0004%
+ \assignmentfalse
+ \else
+ \assignmenttrue
+ \fi}
+
+%D These can be used for cases where we want less tracing noise.
+
+\unexpanded\def\validassignment#1%
+ {\expandafter\syst_helpers_check_else_assignment_if\detokenize{#1}=^^^^0003^^^^0003^^^^0004}
+
+\unexpanded\def\novalidassignment#1%
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=^^^^0003^^^^0003^^^^0004}
+
+%D In \ETEX\ we can use \type {\detokenize} and gain some speed, but in general far
+%D less that 1\% for \type {\convertargument} and nil for \type {\convertcommand}.
+%D This macro is more robust than the pure \TEX\ one, something I found out when
+%D primitives like \type {\jobname} were fed (or something undefined).
+
+\unexpanded\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}}
+\unexpanded\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok
+
+\unexpanded\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}}
+\unexpanded\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}}
+\unexpanded\def\edefconvertedargument#1#2{\edef#1{#2}%
+ \edef#1{\detokenize\expandafter{#1}}}
+\unexpanded\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}}
+\unexpanded\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}}
+\unexpanded\def\xdefconvertedargument#1#2{\xdef#1{#2}%
+ \xdef#1{\detokenize\expandafter{#1}}}
+
+%D When you try to convert a primitive command, you'll find out that the \ETEX\
+%D method fails on for instance \type {\jobname} in the sense that it returns the
+%D filename instead of just \type {\jobname}. So far this does not give real
+%D problems.
+
+%D This is typically a macro that one comes to after reading the \TEX book
+%D carefully. Even then, the definite solution was found after rereading the \TEX
+%D book. The first implementation was:
+%D
+%D \starttyping
+%D \def\doconvertargument#1->#2\\\\{#2}
+%D \stoptyping
+%D
+%D The \type {-}, the delimiter \type {\\\\} and the the second argument are
+%D completely redundant.
+
+%D \macros
+%D {showvalue}
+%D
+%D Ahandy macro, for testing purposes only:
+
+\unexpanded\def\showvalue#1%
+ {\ifcsname#1\endcsname
+ \expandafter\show\csname#1\endcsname
+ \else
+ \show\undefined
+ \fi}
+
+%D \macros
+%D {doifmeaningelse}
+%D
+%D We can use both commands in testing, but alas, not all meanings expand to
+%D something \type {->}. This is no problem in the \ETEX\ implementation, but since
+%D we want compatibility, we need:
+%D
+%D \starttyping
+%D \doifmeaningelse {\next} {\something} {true} {false}
+%D \stoptyping
+%D
+%D Watch the one level expansion of the second argument.
+
+\unexpanded\def\doifelsemeaning#1#2%
+ {\edef\m_syst_string_one{\normalmeaning#1}%
+ \def \m_syst_string_two{#2}%
+ \edef\m_syst_string_two{\normalmeaning\m_syst_string_two}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifmeaningelse\doifelsemeaning
+
+%D \macros
+%D {doifsamestringselse,doifsamestring,doifnotsamestring}
+%D
+%D The next comparison macro converts the arguments into expanded strings. This
+%D command can be used to compare for instance \type {\jobname} with a name stored
+%D in a macro.
+%D
+%D \starttyping
+%D \doifelse {\jobname}{oeps}{YES}{NO}
+%D \doifsamestringelse{\jobname}{oeps}{YES}{NO}
+%D \stoptyping
+
+\def\syst_helpers_if_samestring_else#1#2#3#4%
+ {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#3}}}%
+ \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#4}}}%
+ \ifx\m_syst_string_one\m_syst_string_two\expandafter#1\else\expandafter#2\fi}
+
+\unexpanded\def\doifelsesamestring{\syst_helpers_if_samestring_else\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifsamestring {\syst_helpers_if_samestring_else\firstofoneargument \gobbleoneargument }
+\unexpanded\def\doifnotsamestring {\syst_helpers_if_samestring_else\gobbleoneargument \firstofoneargument }
+
+\let\doifsamestringelse\doifelsesamestring
+
+%D \macros
+%D {ConvertToConstant,ConvertConstantAfter}
+%D
+%D When comparing arguments with a constant, we can get into trouble when this
+%D argument consists of tricky expandable commands. One solution for this is
+%D converting the argument to a string of unexpandable characters. To make
+%D comparison possible, we have to convert the constant too.
+%D
+%D \starttyping
+%D \ConvertToConstant\doifelse {...} {...} {then ...} {else ...}
+%D \stoptyping
+%D
+%D This construction is only needed when the first argument can give troubles.
+%D Misuse can slow down processing.
+%D
+%D \starttyping
+%D \ConvertToConstant\doifelse{\c!alfa} {\c!alfa}{...}{...}
+%D \ConvertToConstant\doifelse{alfa} {\c!alfa}{...}{...}
+%D \ConvertToConstant\doifelse{alfa} {alfa} {...}{...}
+%D \ConvertToConstant\doifelse{alfa \alfa test}{\c!alfa}{...}{...}
+%D \stoptyping
+%D
+%D In examples~2 and~3 both arguments equal, in~1 and~4 they differ.
+
+\unexpanded\def\ConvertToConstant#1#2#3%
+ {\edef\m_syst_string_one{\expandafter\detokenize\expandafter{#2}}%
+ \edef\m_syst_string_two{\expandafter\detokenize\expandafter{#3}}%
+ #1{\m_syst_string_one}{\m_syst_string_two}}
+
+%D When the argument \type{#1} consists of commands, we had better use
+%D
+%D \starttyping
+%D \ConvertConstantAfter\processaction[#1][...]
+%D \ConvertConstantAfter\doifelse{#1}{\v!something}{}{}
+%D \stoptyping
+%D
+%D This commands accepts things like:
+%D
+%D \starttyping
+%D \v!constant
+%D constant
+%D \hbox to \hsize{\rubish}
+%D \stoptyping
+%D
+%D As we will see in the core modules, this macro permits constructions like:
+%D
+%D \starttyping
+%D \setupfootertexts[...][...]
+%D \setupfootertexts[margin][...][...]
+%D \setupfootertexts[\v!margin][...][...]
+%D \stoptyping
+%D
+%D where \type {...} can be anything legally \TEX.
+
+\unexpanded\def\CheckConstantAfter#1#2%
+ {\expandafter\convertargument\v!prefix!\to\ascii
+ \convertargument#1\to#2\relax
+ \doifelseinstring\ascii{#2}
+ {\expandafter\convertargument#1\to#2}
+ {}}
+
+\unexpanded\def\ConvertConstantAfter#1#2#3%
+ {\CheckConstantAfter{#2}\asciia
+ \CheckConstantAfter{#3}\asciib
+ #1{\asciia}{\asciib}}
+
+%D \macros
+%D {assignifempty}
+%D
+%D We can assign a default value to an empty macro using:
+%D
+%D \starttyping
+%D \assignifempty \macros {default value}
+%D \stoptyping
+%D
+%D We don't explicitly test if the macro is defined.
+
+\unexpanded\def\assignifempty#1#2% can be sped up
+ {\doifsomething{#1}{\def#1{#2}}} % {\doifnot{#1}{}{\def#1{#2}}}
+
+%D \macros
+%D {gobbleuntil,grabuntil,gobbleuntilrelax,
+%D processbetween,processuntil}
+%D
+%D In \TEX\ gobbling usually stand for skipping arguments, so here are our gobbling
+%D macros.
+%D
+%D In \CONTEXT\ we use a lot of \type {\start}||\type {\stop} like constructions.
+%D Sometimes, the \type {\stop} is used as a hard coded delimiter like in: %D
+%D \starttyping
+%D \unexpanded\def\startcommand#1\stopcommand%
+%D {... #1 ...}
+%D \stoptyping
+%D
+%D In many cases the \type {\start}||\type {\stop} pair is defined at format
+%D generation time or during a job. This means that we cannot hardcode the \type
+%D {\stop} criterium. Only after completely understanding \type {\csname} and \type
+%D {\expandafter} I was able to to implement a solution, starting with:
+%D
+%D \starttyping
+%D \grabuntil{stop}\command
+%D \stoptyping
+%D
+%D This commands executes, after having encountered \type {\stop} the command \type
+%D {\command}. This command receives as argument the text preceding the \type
+%D {\stop}. This means that:
+%D
+%D \starttyping
+%D \unexpanded\def\starthello%
+%D {\grabuntil{stophello}\message}
+%D
+%D \starthello Hello world!\stophello
+%D \stoptyping
+%D
+%D results in: \type{\message{Hello world!}}.
+
+\let\syst_helpers_grab_indeed\relax
+
+\unexpanded\def\syst_helpers_grab#1#2%
+ {\def\syst_helpers_grab_indeed##1#1{#2{##1}}\syst_helpers_grab_indeed}
+
+\unexpanded\def\grabuntil#1%
+ {\expandafter\syst_helpers_grab\expandafter{\csname#1\endcsname}}
+
+%D The next command build on this mechanism:
+%D
+%D \starttyping
+%D \processbetween{string}\command
+%D \stoptyping
+%D
+%D Here:
+%D
+%D \starttyping
+%D \processbetween{hello}\message
+%D \starthello Hello again!\stophello
+%D \stoptyping
+%D
+%D leads to: \type{\message{Hello again!}}. The command
+%D
+%D \starttyping
+%D \gobbleuntil{sequence}
+%D \stoptyping
+%D
+%D is related to these commands. This one simply throws away
+%D everything preceding \type{\command}.
+
+\let\syst_helpers_gobble_indeed\relax
+
+\unexpanded\def\processbetween#1#2%
+ {\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}}
+
+\unexpanded\def\gobbleuntil#1%
+ {\def\syst_helpers_gobble_indeed##1#1{}\syst_helpers_gobble_indeed}
+
+\unexpanded\def\gobbleuntilrelax#1\relax
+ {}
+
+%D The next one simply expands the pickup up tokens.
+%D
+%D \starttyping
+%D \processuntil{sequence}
+%D \stoptyping
+
+\let\syst_helpers_until_indeed\relax
+
+\unexpanded\def\processuntil#1%
+ {\def\syst_helpers_until_indeed##1#1{##1}\syst_helpers_until_indeed}
+
+%D \macros
+%D {groupedcommand}
+%D
+%D Commands often manipulate argument as in:
+%D
+%D \starttyping
+%D \def\doezomaarwat#1{....#1....}
+%D \stoptyping
+%D
+%D A disadvantage of this approach is that the tokens that form \type{#1} are fixed
+%D the the moment the argument is read in. Normally this is no problem, but for
+%D instance verbatim environments adapt the \CATCODES\ of characters and therefore
+%D are not always happy with already fixed tokens.
+%D
+%D Another problem arises when the argument is grouped not by \type {{}} but by
+%D \type {\bgroup} and \type {\egroup}. Such an argument fails, because the \type
+%D {\bgroup} is een as the argument (which is quite normal).
+%D
+%D The next macro offers a solution for both unwanted situations:
+%D
+%D \starttyping
+%D \groupedcommand {before} {after}
+%D \stoptyping
+%D
+%D Which can be used like:
+%D
+%D \starttyping
+%D \def\cite%
+%D {\groupedcommand{\rightquote\rightquote}{\leftquote\leftquote}}
+%D \stoptyping
+%D
+%D This command is equivalent to, but more 'robust' than:
+%D
+%D \starttyping
+%D \def\cite#1%
+%D {\rightquote\rightquote#1\leftquote\leftquote}
+%D \stoptyping
+%D
+%D \starttyping
+%D \def\rightword%
+%D {\groupedcommand{\hfill\hbox}{\parfillskip\zeropoint}}
+%D
+%D .......... \rightword{the right way}
+%D \stoptyping
+%D
+%D Here \TEX\ typesets \type {\bf the right way} unbreakable at the end of the line.
+%D The solution mentioned before does not work here. We also handle
+%D
+%D \starttyping
+%D to be \bold{bold} or not, that's the question
+%D \stoptyping
+%D
+%D and
+%D
+%D \starttyping
+%D to be {\bold bold} or not, that's the question
+%D \stoptyping
+%D
+%D This alternative checks for a \type {\bgroup} token first. The internal
+%D alternative does not accept the box handling mentioned before, but further
+%D nesting works all right. The extra \type {\bgroup}||\type {\egroup} is needed to
+%D keep \type {\m_syst_helpers_handle_group_after} both into sight and local.
+
+\let\m_syst_helpers_handle_group_after \relax
+\let\m_syst_helpers_handle_group_before\relax
+
+\unexpanded\def\syst_helpers_handle_group_nop
+ {\ifnum\currentgrouptype=\semisimplegroupcode
+ \expandafter\syst_helpers_handle_group_nop_a
+ \else
+ \expandafter\syst_helpers_handle_group_nop_b
+ \fi}
+
+\def\syst_helpers_handle_group_nop_a
+ {\begingroup
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\endgroup
+ \m_syst_helpers_handle_group_b}
+
+\def\syst_helpers_handle_group_nop_b
+ {\bgroup
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\egroup
+ \m_syst_helpers_handle_group_b}
+
+\unexpanded\def\syst_helpers_handle_group_normal
+ {\bgroup
+ \afterassignment\m_syst_helpers_handle_group_normal_before
+ \let\next=}
+
+\def\m_syst_helpers_handle_group_normal_before
+ {\bgroup
+ \m_syst_helpers_handle_group_b
+ \bgroup
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\egroup
+ \aftergroup\egroup}
+
+\unexpanded\def\syst_helpers_handle_group_simple% no inner group (so no kerning interference)
+ {\bgroup
+ \afterassignment\m_syst_helpers_handle_group_simple_before
+ \let\next=}
+
+\def\m_syst_helpers_handle_group_simple_before
+ {\bgroup
+ \aftergroup\m_syst_helpers_handle_group_simple_after
+ \m_syst_helpers_handle_group_b}
+
+\def\m_syst_helpers_handle_group_simple_after
+ {\m_syst_helpers_handle_group_a
+ \egroup}%
+
+\unexpanded\def\syst_helpers_handle_group_pickup% no inner group (so no kerning interference)
+ {\bgroup
+ \afterassignment\m_syst_helpers_handle_group_pickup_before
+ \let\next=}
+
+\def\m_syst_helpers_handle_group_pickup_before
+ {\bgroup
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\egroup
+ \aftergroup\m_syst_helpers_handle_group_p
+ \m_syst_helpers_handle_group_b}
+
+\unexpanded\def\syst_helpers_handle_group_nop_x
+ {\ifnum\currentgrouptype=\semisimplegroupcode
+ \begingroup
+ \aftergroup\endgroup
+ \else
+ \bgroup
+ \aftergroup\egroup
+ \fi
+ \m_syst_helpers_handle_group_b}
+
+\unexpanded\def\syst_helpers_handle_group_normal_x
+ {\bgroup
+ \afterassignment\m_syst_helpers_handle_group_normal_before_x
+ \let\next=}
+
+\def\m_syst_helpers_handle_group_normal_before_x
+ {\bgroup
+ \m_syst_helpers_handle_group_b
+ \bgroup
+ \aftergroup\egroup
+ \aftergroup\egroup}
+
+%D I considered it a nuisance that
+%D
+%D \starttyping
+%D \color[green]
+%D {as grass}
+%D \stoptyping
+%D
+%D was not interpreted as one would expect. This is due to the fact that \type
+%D {\futurelet} obeys blank spaces, and a line||ending token is treated as a blank
+%D space. So the final implementation became:
+
+\unexpanded\def\groupedcommand#1#2%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
+
+\unexpanded\def\groupedcommandcs#1#2%
+ {\let\m_syst_helpers_handle_group_b#1%
+ \let\m_syst_helpers_handle_group_a#2%
+ \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
+
+\unexpanded\def\simplegroupedcommand#1#2%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \futureexpandis\bgroup\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop}
+
+\unexpanded\def\pickupgroupedcommand#1#2#3%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \def\m_syst_helpers_handle_group_p{#2}%
+ \futureexpandis\bgroup\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop}
+
+\unexpanded\def\triggergroupedcommand#1%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
+
+\unexpanded\def\triggergroupedcommandcs#1%
+ {\let\m_syst_helpers_handle_group_b#1%
+ \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
+
+%D Users should be aware of the fact that grouping can interfere with ones paragraph
+%D settings that are executed after the paragraph is closed. One should therefore
+%D explictly close the paragraph with \type {\par}, else the settings will be
+%D forgotten and not applied. So it's:
+%D
+%D \starttyping
+%D \def\BoldRaggedCenter%
+%D {\groupedcommand{\raggedcenter\bf}{\par}}
+%D \stoptyping
+
+%D \macros
+%D {checkdefined}
+%D
+%D The bigger the system, the greater the change that user defined commands collide
+%D with those that are part of the system. The next macro gives a warning when a
+%D command is already defined. We considered blocking the definition, but this is
+%D not always what we want.
+%D
+%D \starttyping
+%D \checkdefined {category} {class} {command}
+%D \stoptyping
+%D
+%D The user is warned with the suggestion to use \type {CAPITALS}. This suggestion
+%D is feasible, because \CONTEXT only defines lowcased macros.
+
+\unexpanded\def\showdefinederror#1#2%
+ {\writestatus\m!system{#1 #2 replaces a macro, use CAPITALS!}}
+
+\unexpanded\def\checkdefined#1#2#3%
+ {\doifdefined{#3}{\showdefinederror{#2}{#3}}}
+
+%D \macros
+%D {GotoPar,GetPar}
+%D
+%D Typesetting a paragraph in a special way can be done by first grabbing the
+%D contents of the paragraph and processing this contents grouped. The next macro
+%D for instance typesets a paragraph in boldface.
+%D
+%D \starttyping
+%D \def\remark#1\par%
+%D {\bgroup\bf#1\egroup}
+%D \stoptyping
+%D
+%D This macro has to be called like
+%D
+%D \starttyping
+%D \remark some text ... ending with \par
+%D \stoptyping
+%D
+%D Instead of \type {\par} we can of course use an empty line. When we started
+%D typesetting with \TEX, we already had produced lots of text in plain \ASCII. In
+%D producing such simple formatted texts, we adopted an open layout, and when
+%D switching to \TEX, we continued this open habit. Although \TEX\ permits a cramped
+%D and badly formatted source, it adds to confusion and sometimes introduces errors.
+%D So we prefer:
+%D
+%D \starttyping
+%D \remark
+%D
+%D some text ... ending with an empty line
+%D \stoptyping
+%D
+%D We are going to implement a mechanism that allows such open specifications. The
+%D definition of the macro handling \type {\remark} becomes:
+%D
+%D \starttyping
+%D \def\remark%
+%D {\BeforePar{\bgroup\bf}%
+%D \AfterPar{\egroup}%
+%D \GetPar}
+%D \stoptyping
+%D
+%D A macro like \type {\GetPar} can be defined in several ways. The recent version,
+%D the fourth one in a row, originally was far more complicated, but some
+%D functionality has been moved to other macros.
+%D
+%D We start with the more simple but in some cases more appropriate alternative is
+%D \type {\GotoPar}. This one leaves \type {\par} unchanged and is therefore more
+%D robust. On the other hand, \type {\AfterPar} is not supported.
+
+\newtoks\BeforePar
+\newtoks\AfterPar
+
+\def\redowithpar\par
+ {\doifelsenextchar\par\redowithpar\dodowithpar}%
+
+\def\dowithpar#1#2%
+ {\def\dodowithpar##1\par{#1##1#2}%
+ \redowithpar\par}
+
+\def\redogotopar\par
+ {\doifelsenextchar\par\redogotopar\dodogotopar}%
+
+\def\dogotopar#1%
+ {\def\dodogotopar{#1}%
+ \redogotopar\par}
+
+\def\dogotoparcs#1%
+ {\let\dodogotopar#1%
+ \redogotopar\par}
+
+\unexpanded\def\GetPar
+ {\expanded
+ {\dowithpar
+ {\the\BeforePar
+ \BeforePar\emptytoks}
+ {\the\AfterPar
+ \BeforePar\emptytoks
+ \AfterPar\emptytoks}}}
+
+\unexpanded\def\GotoPar
+ {\expanded
+ {\dogotopar
+ {\the\BeforePar
+ \BeforePar\emptytoks}}}
+
+%D \macros
+%D {dowithpargument,dowithwargument}
+%D
+%D The next macros are a variation on \type {\GetPar}. When macros expect an
+%D argument, it interprets a grouped sequence of characters a one token. While this
+%D adds to robustness and less ambiguous situations, we sometimes want to be a bit
+%D more flexible, or at least want to be a bit more tolerant to user input.
+%D
+%D We start with a commands that acts on paragraphs. This
+%D command is called as:
+%D
+%D \starttyping
+%D \dowithpargument\command
+%D \dowithpargument{\command ... }
+%D \stoptyping
+%D
+%D In \CONTEXT\ we use this one to read in the titles of chapters, sections etc. The
+%D commands responsible for these activities accept several alternative ways of
+%D argument passing. In these examples, the \type {\par} can be omitted when an
+%D empty line is present.
+%D
+%D \starttyping
+%D \command{...}
+%D \command ... \par
+%D \command
+%D {...}
+%D \command
+%D ... \par
+%D \stoptyping
+
+\let\syst_helpers_next_par\relax
+\let\syst_helpers_next_arg\relax
+
+\unexpanded\def\dowithpargument#1%
+ {\def\syst_helpers_next_par##1 \par{#1{##1}}%
+ \def\syst_helpers_next_arg##1{#1{##1}}%
+ \doifelsenextbgroup\syst_helpers_next_arg{\doifelsenextchar\par{#1{}}\syst_helpers_next_par}}
+
+%D The \type {p} in the previous command stands for paragraph. When we want to act
+%D upon words we can use the \type{w} alternative.
+%D
+%D \starttyping
+%D \dowithwargument\command
+%D \dowithwargument{... \command ...}
+%D \stoptyping
+%D
+%D The main difference bwteen two alternatives is in the handling of \type {\par}'s.
+%D This time the space token acts as a delimiter.
+%D
+%D \starttyping
+%D \command{...}
+%D \command ...
+%D \command
+%D {...}
+%D \command
+%D ...
+%D \stoptyping
+
+\let\syst_helpers_next_war\relax
+\let\syst_helpers_next_arg\relax
+
+\unexpanded\def\dowithwargument#1%
+ {\def\syst_helpers_next_war##1 {#1{##1}}%
+ \def\syst_helpers_next_arg##1{#1{##1}}%
+ \doifelsenextbgroup\syst_helpers_next_arg\syst_helpers_next_war}
+
+%D \macros
+%D {dorepeat,dorepeatwithcommand}
+%D
+%D When doing repetitive tasks, we stromgly advice to use \type {\dorecurse}. The
+%D next alternative however, suits better some of the \CONTEXT\ interface commands.
+%D
+%D \starttyping
+%D \dorepeat[n*\command]
+%D \stoptyping
+%D
+%D The value of the used \COUNTER\ can be called within
+%D \type{\command} by \type{\repeater}.
+%D
+%D A slightly different alternative is:
+%D
+%D \starttyping
+%D \dorepeatwithcommand[n*{...}]\command
+%D \stoptyping
+%D
+%D When we call for something like:
+%D
+%D \starttyping
+%D \dorepeatwithcommand[3*{Hello}]\message
+%D \stoptyping
+%D
+%D we get ourselves three \type {\message{Hello}} messages in a row. In both
+%D commands, the \type {n*} is optional. When this specification is missing, the
+%D command executes once.
+
+\unexpanded\def\dorepeatwithcommand[#1]%
+ {\syst_helpers_repeat_with_command#1*\empty*\relax}
+
+\def\syst_helpers_repeat_with_command#1*#2#3*#4\relax#5%
+ {\ifx#2\empty\syst_helpers_repeat_with_command_again[#1]#5\else\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5\fi}
+
+\def\syst_helpers_repeat_with_command_indeed#1#2#3#4%
+ {\ifx#2\empty % redundant but gives cleaner extensions
+ #4{#1}%
+ \orelse\ifnum#1<\zerocount
+ %\normalexpanded{\dorecurse{\number-\number#1}}{#4{-#2#3}}%
+ \dorecurse{-#1}{#4{-#2#3}}%
+ \orelse\ifx#2+%
+ \dorecurse{#1}{#4{#3}}%
+ \else
+ \dorecurse{#1}{#4{#2#3}}%
+ \fi}
+
+\def\syst_helpers_repeat_with_command_again[#1]#2%
+ {#2{#1}}
+
+%D The extension hook permits something like:
+%D
+%D \starttyping
+%D \bgroup
+%D
+%D \catcode`\*=\superscriptcatcode
+%D
+%D \gdef\syst_helpers_repeat_with_command_again[#1]%
+%D {\redodorepeatwithcommand#1*\empty*\relax}
+%D
+%D \gdef\redodorepeatwithcommand#1*#2#3*#4\relax#5%
+%D {\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5}
+%D
+%D \egroup
+%D \stoptyping
+%D
+%D although one may wonder if changing the catcode of \type {*} is wise.
+
+%D \macros
+%D {doifstringinstringelse}
+%D
+%D The next macro is meant for situations where both strings are macros. This save
+%D some unneeded expansion.
+%D
+%D \starttyping
+%D \def\doifstringinstringelse#1#2%
+%D {\syst_helpers_do_if_in_string_else#1#2%
+%D \expandafter\firstoftwoarguments
+%D \else
+%D \expandafter\secondoftwoarguments
+%D \fi}
+%D \stoptyping
+%D
+%D A bit faster is:
+
+\def\syst_helpers_if_instring_else_indeed#1%
+ {\if#1@%
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\doifelsestringinstring#1#2%
+ {\expandafter\def\expandafter\syst_helpers_if_instring_else\expandafter##\expandafter1#1##2##3^^^^0004%
+ {\syst_helpers_if_instring_else_indeed##2}%
+ \expandafter\expandafter\expandafter\syst_helpers_if_instring_else\expandafter#2#1@@^^^^0004}
+
+\let\doifstringinstringelse\doifelsestringinstring
+
+%D \macros
+%D {appendtoks,prependtoks,appendtoksonce,prependtoksonce,
+%D doifintokselse,flushtoks,dotoks}
+%D
+%D We use tokenlists sparsely within \CONTEXT, because the comma separated lists are
+%D more suitable for the user interface. Nevertheless we have:
+%D
+%D \starttyping
+%D (\doglobal) \appendtoks ... \to\tokenlist
+%D (\doglobal) \prependtoks ... \to\tokenlist
+%D (\doglobal) \flushtoks\tokenlist
+%D \dotoks\tokenlist
+%D \stoptyping
+%D
+%D These macros are clones of the ones implemented in page~378 of Knuth's \TEX book.
+
+\newtoks\t_syst_helpers_scratch
+\let \m_syst_helpers_scratch\empty
+
+\unexpanded\def\appendtoks#1\to#2%
+ {\ifx\dodoglobal\relax
+ \expandafter\toksapp
+ \else
+ \resetglobal
+ \expandafter\gtoksapp
+ \fi#2{#1}}
+
+\unexpanded\def\prependtoks#1\to#2%
+ {\ifx\dodoglobal\relax
+ \expandafter\tokspre
+ \else
+ \resetglobal
+ \expandafter\gtokspre
+ \fi#2{#1}}
+
+\def\syst_helpers_append_toks_indeed
+ {\ifx\dodoglobal\relax
+ \expandafter\toksapp
+ \else
+ \resetglobal
+ \expandafter\gtoksapp
+ \fi\m_syst_helpers_scratch\t_syst_helpers_scratch}
+
+\def\syst_helpers_prepend_toks_indeed
+ {\ifx\dodoglobal\relax
+ \expandafter\tokspre
+ \else
+ \resetglobal
+ \expandafter\gtokspre
+ \fi\m_syst_helpers_scratch\t_syst_helpers_scratch}
+
+\unexpanded\def\appendtoksonce#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch{#1}%
+ \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+ \donothing
+ \syst_helpers_append_toks_indeed}
+
+\unexpanded\def\prependtoksonce#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch{#1}%
+ \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+ \donothing
+ \syst_helpers_prepend_toks_indeed}
+
+%D The test macro:
+
+\unexpanded\def\doifelseintoks#1#2% #1 en #2 zijn toks
+ {\edef\asciia{\detokenize\expandafter{\the#1}}%
+ \edef\asciib{\detokenize\expandafter{\the#2}}%
+ \doifelsestringinstring\asciia\asciib}
+
+\let\doifintokselse\doifelseintoks
+
+%D Moved from \type {lxml-ini.tex} to here. This one is for generators that collect
+%D stuff piecewise, which is sometimes hard on mechanisms that grab content using
+%D delimiters:
+%D
+%D \starttyping
+%D \startcollecting
+%D \startcollect \bTABLE \stopcollect
+%D \startcollect \bTR \stopcollect
+%D \startcollect \bTD \stopcollect
+%D \startcollect foo\stopcollect
+%D \startcollect \eTD \stopcollect
+%D \startcollect \bTD \stopcollect
+%D \startcollect bar\stopcollect
+%D \startcollect \eTD \stopcollect
+%D \startcollect \eTR \stopcollect
+%D \startcollect \eTABLE \stopcollect
+%D \stopcollecting
+%D \stoptyping
+
+\newtoks \collectingtoks
+
+\unexpanded\def\startcollect #1\stopcollect {\toksapp \collectingtoks{#1}}
+\unexpanded\def\startexpandedcollect#1\stopexpandedcollect{\etoksapp\collectingtoks{#1}}
+
+\unexpanded\def\startcollecting{\collectingtoks\emptytoks}
+\unexpanded\def\stopcollecting {\the\collectingtoks}
+
+\unexpanded\def\collect {\toksapp \collectingtoks}
+\unexpanded\def\collectexpanded{\etoksapp\collectingtoks}
+
+%D A nice one too:
+
+% {\scratchtoks{abc} \removetoks b\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{abc} \removetoks x\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{} \removetoks x\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{xaa} \removetoks x\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{a\relax b} \removetoks \relax\from\scratchtoks [\showthe\scratchtoks]}
+
+\unexpanded\def\removetoks#1\from#2%
+ {\def\syst_helpers_remove_toks##1#1##2\empty\empty\empty##3^^^^0004%
+ {\def\m_syst_string_one{##3}%
+ \ifx\m_syst_string_one\empty#2{##1}\else#2{##1##2}\fi}%
+ \expandafter\syst_helpers_remove_toks\the#2\empty\empty\empty#1\empty\empty\empty^^^^0004}
+
+%D Also:
+
+\unexpanded\def\appendetoks#1\to#2%
+ {\ifx\dodoglobal\relax
+ \expandafter\etoksapp
+ \else
+ \resetglobal
+ \expandafter\xtoksapp
+ \fi#2{#1}}
+
+\unexpanded\def\prependetoks#1\to#2%
+ {\ifx\dodoglobal\relax
+ \expandafter\etokspre
+ \else
+ \resetglobal
+ \expandafter\xtokspre
+ \fi#2{#1}}
+
+%D Hm.
+
+\unexpanded\def\flushtoks#1% nb: can reassign to #1 again, hence the indirectness
+ {\t_syst_helpers_scratch#1\relax
+ \dodoglobal#1\emptytoks
+ \the\t_syst_helpers_scratch\relax}
+
+\let\dotoks\the
+
+%D \macros
+%D {beforesplitstring,aftersplitstring}
+%D
+%D These both commands split a string at a given point in two
+%D parts, so \type{x.y} becomes \type{x} or \type{y}.
+%D
+%D \starttyping
+%D \beforesplitstring test.tex\at.\to\filename
+%D \aftersplitstring test.tex\at.\to\extension
+%D \stoptyping
+%D
+%D The first routine looks (and is indeed) a bit simpler than the second one. The
+%D alternative looking more or less like the first one did not always give the
+%D results we needed. Both implementations show some insight in the manipulation of
+%D arguments.
+
+\let\syst_helpers_split_string\relax
+
+\unexpanded\def\beforesplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2#2##3\\%
+ {\def#3{##1}}%
+ \expandafter\syst_helpers_split_string#1#2#2\\}
+
+\unexpanded\def\aftersplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2@@@##3\\%
+ {\def#3{##2}}%
+ \expandafter\syst_helpers_split_string#1@@@#2@@@\\}
+
+%D \macros
+%D {splitstring,greedysplitstring}
+%D
+%D A bonus macro.
+
+\unexpanded\def\splitstring#1\at#2\to#3\and#4%
+ {\def\syst_helpers_split_string##1#2##2\empty\empty\empty##3\\%
+ {\def#3{##1}%
+ \def\syst_helpers_split_string{##3}%
+ \ifx\syst_helpers_split_string\empty
+ \let#4\empty
+ \else
+ \def#4{##2}%
+ \fi}%
+ \expandafter\syst_helpers_split_string#1\empty\empty\empty#2\empty\empty\empty\\}
+
+\unexpanded\def\greedysplitstring#1\at#2\to#3\and#4%
+ {\edef\asciib{#1}%
+ \let\asciic\asciib
+ \let#3\empty
+ \let#4\empty
+ \doloop
+ {\expandafter\splitstring\asciib\at#2\to\asciia\and\asciib
+ \ifx\asciib\empty
+ \exitloop
+ \else
+ % not \edef#3{\ifx#3\empty\else#3#2\fi\asciia} else
+ % /root/path fails because then #3==empty
+ \edef#3{\ifcase\recurselevel\or\else#3#2\fi\asciia}%
+ \let#4\asciib
+ \fi}%
+ \ifx#3\empty\let#3\asciic\fi}
+
+%D \macros
+%D {beforetestandsplitstring,
+%D aftertestandsplitstring,
+%D testandsplitstring}
+
+\unexpanded\def\beforetestandsplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2#2##3##4\\%
+ {\ifx##3\empty\let#3\empty\else\def#3{##1}\fi}%
+ \expandafter\syst_helpers_split_string#1#2#2\empty\\}
+
+\unexpanded\def\aftertestandsplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string ##1#2##2@@@##3##4\\%
+ {\ifx##3\empty\let#3\empty\else\def#3{##2}\fi}%
+ \expandafter\syst_helpers_split_string #1@@@#2@@@\empty\\}
+
+\def\testandsplitstring#1\at#2\to#3\and#4%
+ {\def\syst_helpers_split_string##1#2##2#2##3##4\\%
+ {\ifx##3\empty\let#3\empty\let#4\empty\else\def#3{##1}\def#4{##2}\fi}%
+ \expandafter\syst_helpers_split_string#1#2#2\empty\\}
+
+%D \macros
+%D {splitatperiod,
+%D {splitatcomma,
+%D splitatasterisk,
+%D splitatcolon,
+%D splitatcolons}
+
+\unexpanded\def\splitatperiod #1{\normalexpanded{\syst_helpers_splitatperiod #1}..\relax}
+\unexpanded\def\splitatcomma #1{\normalexpanded{\syst_helpers_splitatcomma #1},,\relax} % not at ", "
+\unexpanded\def\splitatasterisk#1{\normalexpanded{\syst_helpers_splitatasterisk#1}**\relax}
+\unexpanded\def\splitatcolon #1{\normalexpanded{\syst_helpers_splitatcolon #1}::\relax}
+\unexpanded\def\splitatcolons #1{\normalexpanded{\syst_helpers_splitatcolons #1}::::\relax}
+
+\unexpanded\def\syst_helpers_splitatperiod #1.#2.#3\relax#4#5{\def#4{#1}\def#5{#2}}
+\unexpanded\def\syst_helpers_splitatcomma #1,#2,#3\relax#4#5{\def#4{#1}\def#5{#2}}
+\unexpanded\def\syst_helpers_splitatasterisk #1*#2*#3\relax#4#5{\def#4{#1}\def#5{#2}}
+\unexpanded\def\syst_helpers_splitatcolon #1:#2:#3\relax#4#5{\def#4{#1}\def#5{#2}}
+\unexpanded\def\syst_helpers_splitatcolons #1::#2::#3\relax#4#5{\edef#4{#1}\edef#5{#2}}
+
+%D \macros
+%D {removesubstring}
+%D
+%D A first application of the two routines defined above is:
+%D
+%D \starttyping
+%D \removesubstring-\from first-last\to\nothyphenated
+%D \stoptyping
+%D
+%D Which in terms of \TEX\ looks like:
+
+\unexpanded\def\removesubstring#1\from#2\to#3%
+ {\splitstring#2\to\m_syst_string_one\and\m_syst_string_two
+ \dodoglobal#3{\m_syst_string_one\m_syst_string_two}}
+
+%D \macros
+%D {appendtocommalist,prependtocommalist,
+%D addtocommalist,removefromcommalist}
+%D
+%D When working with comma separated lists, one sooner or later want the tools to
+%D append or remove items from such a list. When we add an item, we first check if
+%D it's already there. This means that every item in the list is unique.
+%D
+%D \starttyping
+%D \addtocommalist {alfa} \name
+%D \addtocommalist {beta} \name
+%D \addtocommalist {gamma} \name
+%D \removefromcommalist {beta} \name
+%D \stoptyping
+%D
+%D These commands can be prefixed with \type {\doglobal}. The implementation of the
+%D second command is more complecated, because we have to take leading spaces into
+%D account. Keep in mind that users may provide lists with spaces after the commas.
+%D When one item is left, we also have to get rid of trailing spaces.
+%D
+%D \starttyping
+%D \def\words{alfa, beta, gamma, delta}
+%D \def\words{alfa,beta,gamma,delta}
+%D \stoptyping
+%D
+%D Removing an item takes more time than adding one. A fast appending alternative,
+%D without any testing, is also provided:
+%D
+%D \starttyping
+%D \appendtocommalist {something} \name
+%D \prependtocommalist {something} \name
+%D \stoptyping
+%D
+%D This can be implemented as follows:
+%D
+%D \starttyping
+%D \def\appendtocommalist#1#2%
+%D {\ifx#2\empty
+%D \dodoglobal\edef#2{#1}%
+%D \else % no test on empty
+%D \dodoglobal\edef#2{#2,#1}%
+%D \fi}
+%D
+%D \def\prependtocommalist#1#2%
+%D {\ifx#2\empty
+%D \dodoglobal\edef#2{#1}%
+%D \else % no test on empty
+%D \dodoglobal\edef#2{#1,#2}%
+%D \fi}
+%D \stoptyping
+%D
+%D The faster alternatives are:
+
+\unexpanded\def\appendtocommalist#1#2%
+ {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}
+
+\unexpanded\def\prependtocommalist#1#2%
+ {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}
+
+\unexpanded\def\addtocommalist#1#2% {item} \cs
+ {\rawdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}
+
+\unexpanded\def\pretocommalist#1#2% {item} \cs
+ {\rawdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
+
+\unexpanded\def\robustdoifelseinset#1#2%
+ {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#1}}}%
+ \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#2}}}%
+ \rawdoifelseinset\m_syst_string_one\m_syst_string_two}
+
+\let\robustdoifinsetelse\robustdoifelseinset
+
+\unexpanded\def\robustaddtocommalist#1#2% {item} \cs
+ {\robustdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}
+
+\unexpanded\def\robustpretocommalist#1#2% {item} \cs
+ {\robustdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
+
+\unexpanded\def\xsplitstring#1#2% \cs {str}
+ {\def\syst_helpers_split_string##1,#2,##2,#2,##3\\%
+ {\edef\m_syst_string_one{\bcleanedupcommalist##1\empty\empty\relax}%
+ \edef\m_syst_string_two{\acleanedupcommalist##2,,\relax}}%
+ \expandafter\syst_helpers_split_string\expandafter,#1,,#2,,#2,\\}
+
+\def\bcleanedupcommalist#1#2#3\relax{\if#1,\else#1\fi\if#2,\else#2\fi#3}
+\def\bcleanedupcommalist#1#2\relax{\if#1,\else#1\fi#2}
+\def\acleanedupcommalist#1,,#2\relax{#1}
+
+\unexpanded\def\removefromcommalist#1#2% to be sped up
+ {\rawdoifelseinset{#1}#2%
+ {\normalexpanded{\xsplitstring\noexpand#2{#1}}%
+ \dodoglobal\edef#2%
+ {\ifx\m_syst_string_one\empty
+ \m_syst_string_two
+ \else
+ \m_syst_string_one\ifx\m_syst_string_two\empty\else,\m_syst_string_two\fi
+ \fi}}
+ \resetglobal}
+
+%D \macros
+%D {substituteincommalist}
+%D
+%D Slow but seldom used, so for the moment we stick to this implementation.
+%D
+%D \starttyping
+%D \substituteincommalist{old}{new}{list}
+%D \stoptyping
+
+\def\syst_helpers_substitute_in_comma_list_step#1%
+ {\edef\m_syst_string_three{#1}%
+ \ifx\m_syst_string_one\m_syst_string_three
+ \ifx\m_syst_string_two\empty \else
+ \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi\m_syst_string_two}%
+ \fi
+ \else
+ \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi#1}%
+ \fi}
+
+\unexpanded\def\substituteincommalist#1#2#3% old, new, list (slooow)
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \let\m_syst_string_four\empty
+ \normalexpanded{\rawprocesscommacommand[#3]}\syst_helpers_substitute_in_comma_list_step
+ \let#3\m_syst_string_four}
+
+%D \macros
+%D {replaceincommalist}
+%D
+%D The next macro can be used to replace an indexed element in a commalist:
+%D
+%D \starttyping
+%D \replaceincommalist\MyList{2}
+%D \stoptyping
+%D
+%D Element~2 will be replaced by the current meaning of the macro \type
+%D {\newcommalistelement}. The old meaning is saved in \type {\commalistelement}.
+%D The replacement honors grouped items, like in:
+%D
+%D \starttyping
+%D \def\MyList{a,b,c,d,e,f} \replaceincommalist\MyList{3}
+%D \def\MyList{a,b,c,d,e,f} \replaceincommalist\MyList{3}
+%D \def\MyList{a,{b,c},d,e,f} \replaceincommalist\MyList{3}
+%D \def\MyList{a,b,c,{d,e,f}} \replaceincommalist\MyList{3}
+%D \stoptyping
+%D
+%D This macro was used in the bibtex code (and is probably no longer needed).
+
+\newcount\c_syst_helpers_comma_list_index
+\let \m_syst_helpers_comma_list_target\empty
+
+\let\newcommalistelement\empty
+
+\def\syst_helpers_replace_in_comma_list_step#1%
+ {\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax
+ \ifx\newcommalistelement\empty\else
+ \ifx\m_syst_helpers_comma_list_target\empty
+ \let\m_syst_helpers_comma_list_target\newcommalistelement
+ \else
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter
+ \m_syst_helpers_comma_list_target\expandafter\expandafter\expandafter
+ {\expandafter\m_syst_helpers_comma_list_target\expandafter,\newcommalistelement}%
+ \fi
+ \fi
+ \def\commalistelement{#1}%
+ \else
+ \ifx\m_syst_helpers_comma_list_target\empty
+ \ifx\nexttoken\bgroup % is known -)
+ \def\m_syst_helpers_comma_list_target{{#1}}%
+ \else
+ \def\m_syst_helpers_comma_list_target{#1}%
+ \fi
+ \else
+ \ifx\nexttoken\bgroup % is known -)
+ \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,{#1}}%
+ \else
+ \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,#1}%
+ \fi
+ \fi
+ \fi
+ \advance\commalistcounter\plusone}
+
+\unexpanded\def\replaceincommalist#1#2% #1 = commalistelement #2 = position starts at 1
+ {\c_syst_helpers_comma_list_index#2\relax
+ \let\m_syst_helpers_comma_list_target\empty
+ \let\commalistelement\empty
+ \commalistcounter\plusone
+ \expandafter\processcommalist\expandafter[#1]\syst_helpers_replace_in_comma_list_step
+ \dodoglobal\let#1\m_syst_helpers_comma_list_target}
+
+%D \macros
+%D {globalprocesscommalist}
+%D
+%D The commalist processing commands are characterized by the fact that the way they
+%D handle expansion as well as the fact that they can be nested. This makes them
+%D kind of useless for handling comma lists in alignments. In these situations the
+%D next macro can be of use.
+
+\let\m_syst_helpers_comma_list_command_global\empty
+
+\def\syst_helpers_comma_list_command_global_step#1,%
+ {\if]#1\else
+ \m_syst_helpers_comma_list_command_global{#1}%
+ \expandafter\syst_helpers_comma_list_command_global_step
+ \fi}
+
+\unexpanded\def\globalprocesscommalist[#1]#2%
+ {\glet\m_syst_helpers_comma_list_command_global#2%
+ \expandafter\syst_helpers_comma_list_command_global_step#1,],}
+
+%D \macros
+%D {withoutpt,PtToCm,
+%D numberofpoints,dimensiontocount}
+%D
+%D We can convert point into centimeters with:
+%D
+%D \starttyping
+%D \PtToCm{dimension}
+%D \stoptyping
+
+{\catcode`\.=\othercatcode
+ \catcode`\p=\othercatcode
+ \catcode`\t=\othercatcode
+ \gdef\WITHOUTPT#1pt{#1}}
+
+\def\withoutpt#1%
+ {\expandafter\WITHOUTPT#1}
+
+%D The capitals are needed because \type {p} and \type {t} have catcode~12, while
+%D macronames only permit tokens with the catcode~11. As a result we cannot use the
+%D \type {.group} primitives. Those who want to know more about this kind of
+%D manipulations, we advice to study the \TEX book in detail. Because this macro
+%D does not do any assignment, we can use it in the following way too.
+
+\def\PtToCm#1%
+ {\withoutpt\the\dimexpr0.0351459804\dimexpr#1\relax\relax cm}
+
+%D We also support:
+%D
+%D \starttyping
+%D \numberofpoints {dimension}
+%D \dimensiontocount {dimension} {\count}
+%D \stoptyping
+%D
+%D Both macros return a rounded number.
+
+% \dimensiontocount{10.49pt}\scratchcounter \the\scratchcounter / \numberofpoints{10.49pt}
+% \dimensiontocount{10.51pt}\scratchcounter \the\scratchcounter / \numberofpoints{10.51pt}
+
+\def\dimensiontocount#1#2{#2\numexpr\dimexpr#1\relax/\maxcard\relax}
+\def\numberofpoints #1{\the\numexpr\dimexpr#1\relax/\maxcard\relax}
+
+%D \macros
+%D {swapdimens,swapcounts,swapmacros,
+%D globalswapdimens,globalswapcounts,globalswapmacros}
+%D
+%D Simple but effective are the next two macros. There name exactly states their
+%D purpose.
+
+\newdimen\d_syst_helpers_swapped
+\newcount\c_syst_helpers_swapped
+\let \m_syst_helpers_swapped\relax
+
+\unexpanded\def\swapdimens#1#2{\d_syst_helpers_swapped #1\relax#1#2\relax#2\d_syst_helpers_swapped}
+\unexpanded\def\swapcounts#1#2{\c_syst_helpers_swapped #1\relax#1#2\relax#2\c_syst_helpers_swapped}
+\unexpanded\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let #1#2\let #2\m_syst_helpers_swapped}
+
+\unexpanded\def\globalswapdimens#1#2{\d_syst_helpers_swapped #1\global#1#2\global#2\d_syst_helpers_swapped}
+\unexpanded\def\globalswapcounts#1#2{\c_syst_helpers_swapped #1\global#1#2\global#2\c_syst_helpers_swapped}
+\unexpanded\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\glet #1#2\glet #2\m_syst_helpers_swapped}
+
+%D \macros
+%D {pushmacro,popmacro}
+%D
+%D Premature and a bit of beta, we offer:
+%D
+%D \starttyping
+%D \pushmacro\macro
+%D \popmacro\macro
+%D \stoptyping
+%D
+%D Beware: global!
+
+\installsystemnamespace{localpushedmacro}
+\installsystemnamespace{globalpushedmacro}
+
+\let\m_syst_helpers_push_macro\empty
+
+\newcount\c_syst_helpers_pop_count
+
+\def\syst_helpers_push_macro_new_global
+ {\expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\plusone}
+
+\def\syst_helpers_push_macro_new_local
+ {\expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\plusone}
+
+\unexpanded\def\globalpushmacro#1%
+ {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+ \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\lastnamedcs\plusone
+ \else
+ \syst_helpers_push_macro_new_global
+ \fi
+ \expandafter\glet\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
+
+\unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup
+ {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+ \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\lastnamedcs\plusone
+ \else
+ \syst_helpers_push_macro_new_local
+ \fi
+ \expandafter\glet\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
+
+\unexpanded\def\globalpopmacro#1%
+ {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+ \c_syst_helpers_pop_count\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\lastnamedcs \minusone
+ \expandafter\glet\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname}
+
+\unexpanded\def\localpopmacro#1%
+ {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+ \c_syst_helpers_pop_count\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\lastnamedcs \minusone
+ \expandafter\let\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname}
+
+\let\pushmacro\localpushmacro
+\let\popmacro \localpopmacro
+
+%D \macros
+%D {setlocalhsize,distributedhsize}
+%D
+%D Sometimes we need to work with the \type{ \hsize} that is corrected for
+%D indentation and left and right skips. The corrected value is available in \type
+%D {\localhsize}, which needs to be calculated with \type {\setlocalhsize} first. %D
+%D
+%D \starttyping
+%D \setlocalhsize \hbox to \localhsize{...}
+%D \setlocalhsize[-1em] \hbox to \localhsize{...}
+%D \setlocalhsize[.5ex] \hbox to \localhsize{...}
+%D \stoptyping
+%D
+%D These examples show us that an optional can be used. The value provided is added
+%D to \type {\localhsize}.
+
+\newdimen\localhsize
+
+\unexpanded\def\setlocalhsize % don't change !
+ {\doifelsenextoptional
+ \syst_helpers_set_local_hsize_yes
+ \syst_helpers_set_local_hsize_nop}
+
+\def\syst_helpers_set_local_hsize_nop
+ {\localhsize\availablehsize}
+
+\def\syst_helpers_set_local_hsize_yes[#1]%
+ {\syst_helpers_set_local_hsize_nop
+ \advance\localhsize#1\relax}
+
+\def\availablehsize
+ {\dimexpr
+ \hsize-\leftskip-\rightskip
+ \ifnum\hangafter<\zerocount
+ \ifdim\hangindent>\zeropoint-\else+\fi\hangindent
+ \fi
+ \relax}
+
+\def\distributedhsize#1#2#3%
+ {\dimexpr(#1-\numexpr#3-1\relax\dimexpr#2\relax)/#3\relax}
+
+\def\hsizefraction#1#2%
+ {\dimexpr#1/#2\relax}
+
+%D \macros
+%D {doifvalue,doifnotvalue,doifelsevalue,
+%D doifnothing,doifsomething,doifelsenothing,
+%D doifvaluenothing,doifvaluesomething,doifelsevaluenothing}
+%D
+%D These \type {\if} commands can be used to access macros (or variables) that are
+%D normally accessed by using \type {\getvalue}. Using these alternatives safes us
+%D three tokens per call. Anyone familiar with the not||values ones, can derive
+%D their meaning from the definitions.
+
+\unexpanded\def\doifvalue#1#2%
+ {\iftok{\csname#1\endcsname}{#2}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotvalue#1#2%
+ {\iftok{\csname#1\endcsname}{#2}%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifelsevalue#1#2%
+ {\iftok{\csname#1\endcsname}{#2}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifnothing#1%
+ {\iftok{#1}\emptytoks
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifsomething#1%
+ {\iftok{#1}\emptytoks
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifelsenothing#1%
+ {\iftok{#1}\emptytoks
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifelsesomething#1%
+ {\iftok{#1}\emptytoks
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\unexpanded\def\doifvaluenothing#1%
+ {\iftok{\csname#1\endcsname}\emptytoks
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifvaluesomething#1%
+ {\iftok{\csname#1\endcsname}\emptytoks
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifelsevaluenothing#1%
+ {\iftok{\csname#1\endcsname}\emptytoks
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifvalueelse \doifelsevalue
+\let\doifnothingelse \doifelsenothing
+\let\doifsomethingelse \doifelsesomething
+\let\doifvaluenothingelse\doifelsevaluenothing
+
+%D \macros
+%D {doifemptyelsevalue, doifemptyvalue, doifnotemptyvalue}
+%D
+%D Also handy:
+
+\def\doifelseemptyvalue#1%
+ {\expandafter\ifx\csname#1\endcsname\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifemptyvalueelse\doifelseemptyvalue
+
+\def\doifemptyvalue#1%
+ {\expandafter\ifx\csname#1\endcsname\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doifnotemptyvalue#1%
+ {\expandafter\ifx\csname#1\endcsname\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {doifallcommonelse}
+%D
+%D A complete match of two sets can be tested with \type {\doifallcommonelse}, where
+%D the first two arguments are sets.
+
+\def\syst_helpers_do_if_all_common_else#1#2#3#4% slow
+ {\def\syst_helpers_do_common_check_all##1%
+ {\doifnotinset{##1}{#4}\donefalse
+ \ifdone\else\expandafter\quitcommalist\fi}%
+ \donetrue
+ \processcommalist[#3]\syst_helpers_do_common_check_all
+ \ifdone\expandafter#1\else\expandafter#2\fi}
+
+\unexpanded\def\doifelseallcommon{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument }
+\unexpanded\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments }
+
+\let\doifallcommonelse\doifelseallcommon
+
+%D \macros
+%D {DOIF,DOIFELSE,DOIFNOT}
+%D
+%D \TEX\ is case sensitive. When comparing arguments, this feature sometimes is less
+%D desirable, for instance when we compare filenames. The next three alternatives
+%D upcase their arguments before comparing them.
+%D
+%D \starttyping
+%D \DOIF {string1} {string2} {...}
+%D \DOIFNOT {string1} {string2} {...}
+%D \DOIFELSE {string1} {string2} {then ...}{else ...}
+%D \stoptyping
+%D
+%D We have to use a two||step implementation, because the
+%D expansion has to take place outside \type{\uppercase}.
+%D
+%D These might end up as \LUA based helpers (i.e. consider these
+%D obsolete:
+
+\unexpanded\def\syst_helpers_do_IF#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\syst_helpers_do_IF_NOT#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\syst_helpers_do_IF_ELSE#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\syst_helpers_do_IF_INSTRING_ELSE#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFINSTRINGELSE #1#2{\normalexpanded{\syst_helpers_do_IF_INSTRING_ELSE{#1}{#2}}}% will become obsolete
+
+%D \macros
+%D {dosingleargumentwithset,
+%D dodoubleargumentwithset,dodoubleemptywithset,
+%D dotripleargumentwithset,dotripleemptywithset}
+%D
+%D These maybe too mysterious macros enable us to handle more than one setup at once.
+%D
+%D \starttyping
+%D \dosingleargumentwithset \command[#1]
+%D \dodoubleargumentwithset \command[#1][#2]
+%D \dotripleargumentwithset \command[#1][#2][#3]
+%D \dodoubleemptywithset \command[#1][#2]
+%D \dotripleemptywithset \command[#1][#2][#3]
+%D \stoptyping
+%D
+%D The first macro calls \type {\command[##1]} for each string in the set~\type
+%D {#1}. The second one calls for \typ {\command [##1][#2]} and the third, well one
+%D may guess. These commands support constructions like:
+%D
+%D \starttyping
+%D \def\dodefinesomething[#1][#2]%
+%D {\getparameters[\??xx#1][#2]}
+%D
+%D \unexpanded\def\definesomething%
+%D {\dodoubleargumentwithset\dodefinesomething}
+%D \stoptyping
+%D
+%D Which accepts calls like:
+%D
+%D \starttyping
+%D \definesomething[alfa,beta,...][variable=...,...]
+%D \stoptyping
+
+\let\m_syst_helpers_with_set_command\empty
+\let\syst_helpers_with_set_step \relax
+
+\def\syst_helpers_with_set_double[#1][#2]%
+ {\doifsomething{#1}%
+ {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}%
+ \processcommalist[#1]\syst_helpers_with_set_step}}
+
+\def\syst_helpers_with_set_triple[#1][#2][#3]%
+ {\doifsomething{#1}%
+ {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}%
+ \processcommalist[#1]\syst_helpers_with_set_step}}
+
+\def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command
+\def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command
+
+\def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command
+\def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command
+
+%D \macros
+%D {stripcharacters,stripspaces}
+%D
+%D The next command was needed first when we implemented the \CONTEXT\ interactivity
+%D macros. When we use labeled destinations, we often cannot use all the characters
+%D we want. We therefore strip some of the troublemakers, like spaces, from the
+%D labels before we write them to the \DVI||file, which passes them to for instance
+%D a \POSTSCRIPT\ file.
+%D
+%D \starttyping
+%D \stripspaces\from\one\to\two
+%D \stoptyping
+%D
+%D Both the old string \type{\one} and the new one \type{\two}
+%D are expanded. This command is a special case of:
+%D
+%D \starttyping
+%D \stripcharacter\char\from\one\to\two
+%D \stoptyping
+%D
+%D As we can see below, spaces following a control sequence are to enclosed in \type
+%D {{}}.
+
+\let\m_syst_helpers_strip_character\empty
+
+\unexpanded\def\stripcharacter#1\from#2\to#3%
+ {\def\syst_helpers_strip_character##1#1##2\end
+ {\edef\m_syst_helpers_strip_character{\m_syst_helpers_strip_character##1}%
+ \doifnotempty{##2}{\syst_helpers_strip_character##2\end}}%
+ \let\m_syst_helpers_strip_character\empty
+ \edef\m_syst_string_one{#2}%
+ \expandafter\syst_helpers_strip_character\m_syst_string_one#1\end
+ \dodoglobal\let#3\m_syst_helpers_strip_character}
+
+\unexpanded\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2
+ {\stripcharacter{ }\from#1\to#2}
+
+%D \macros
+%D {unspacestring}
+%D
+%D The next macro does the same but is more compatible with other macros, like \type
+%D {\convert...}.
+
+\unexpanded\def\unspacestring#1\to#2%
+ {\stripcharacter{ }\from#1\to#2}
+
+%D \macros
+%D {executeifdefined}
+%D
+%D \CONTEXT\ uses one auxiliary file for all data concerning tables of contents,
+%D references, two||pass optimizations, sorted lists etc. This file is loaded as
+%D many times as needed. During such a pass we skip the commands thate are of no use
+%D at that moment. Because we don't want to come into trouble with undefined
+%D auxiliary commands, we call the macros in a way similar to \type {\getvalue}. The
+%D next macro take care of such executions and when not defined, gobbles the
+%D unwanted arguments.
+%D
+%D \starttyping
+%D \executeifdefined{name}\gobbleoneargument
+%D \stoptyping
+%D
+%D We can of course gobble more arguments using the appropriate gobbling command.
+
+\def\executeifdefined#1% #2 / never change this one again
+ {\ifcsname#1\endcsname
+ % \csname#1\expandafter\expandafter\expandafter\endcsname\expandafter\gobbleoneargument
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D This one also has the advantage that it is fully expandable and that it can be
+%D used after an assignment.
+
+%D \macros
+%D {doifsomespaceelse}
+%D
+%D The next command checks a string on the presence of a space and executed a
+%D command accordingly.
+%D
+%D \starttyping
+%D \doifsomespaceelse {tekst} {then ...} {else ...}
+%D \stoptyping
+%D
+%D We use this command in \CONTEXT\ for determing if an argument must be broken into
+%D words when made interactive. Watch the use of \type {\noexpand}.
+
+%D Is this one still needed?
+
+\def\syst_helpers_if_some_space_else#1 #2#3^^^^0004{\if\noexpand#2@}
+
+\def\doifelsesomespace#1% % #2#3%
+ {\syst_helpers_if_some_space_else#1 @ @^^^^0004% #3\else#2\fi}
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doifsomespaceelse\doifelsesomespace
+
+%D \macros
+%D {processseparatedlist}
+%D
+%D Maybe a bit late, but here is a more general version of the \type
+%D {\processcommalist} command. This time we don't handle nesting but accept
+%D arbitrary seperators.
+%D
+%D \starttyping
+%D \processseparatedlist[list][separator]\command
+%D \stoptyping
+%D
+%D One can think of things like:
+%D
+%D \starttyping
+%D \processseparatedlist[alfa+beta+gamma][+]\message
+%D \stoptyping
+%D
+%D We want to handle all situations, like:
+%D
+%D \startbuffer
+%D \processseparatedlist[{aap noot}] [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \processseparatedlist[{aap} {noot}][ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \processseparatedlist[aap {noot}] [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \processseparatedlist[aap noot] [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Therefore we smuggle a \type {\relax} in front of the argument, which we remove
+%D afterwards.
+
+\let\syst_helpers_process_separated_list_step\relax
+
+\def\syst_helpers_process_separated_list#1]#2[#3]#4%
+ {\def\syst_helpers_process_separated_list_step##1##2#3%
+ {\def\m_syst_string_one{##2}% suggested by VZ
+ \if]##1%
+ \let\syst_helpers_process_separated_list_step\relax
+ \orelse\ifx\blankspace\m_syst_string_one
+ #4{##1}%
+ \orelse\if]##2%
+ \let\syst_helpers_process_separated_list_step\relax
+ \else
+ #4{##1##2}%
+ \fi
+ \syst_helpers_process_separated_list_step}%
+ \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#3]#3}
+
+\unexpanded\def\processseparatedlist[%
+ {\syst_helpers_process_separated_list\relax}
+
+%D \macros
+%D {processlist}
+%D
+%D An even more general list processing macro is the following one:
+%D
+%D \starttyping
+%D \processlist{beginsym}{endsym}{separator}\docommand list
+%D \stoptyping
+%D
+%D This one supports arbitrary open and close symbols as well as user defined
+%D separators.
+%D
+%D \starttyping
+%D \processlist(){=>}\docommand(a=>b=>c=>d)
+%D \stoptyping
+
+\let\syst_helpers_process_any_list \relax
+\let\syst_helpers_process_any_list_indeed\relax
+\let\syst_helpers_process_any_list_step \relax
+
+\unexpanded\def\processlist#1#2#3#4% no blank skipping !
+ {\def\syst_helpers_process_any_list_indeed##1#2%
+ {\def\syst_helpers_process_any_list_step####1####2#3%
+ {\ifx#2####1%
+ \let\syst_helpers_process_any_list_step\relax
+ \orelse\ifx#2####2%
+ \let\syst_helpers_process_any_list_step\relax
+ \else
+ #4{####1####2}%
+ \fi
+ \syst_helpers_process_any_list_step}%
+ \expandafter\syst_helpers_process_any_list_step\gobbleoneargument##1#3#2#3}%
+ \def\syst_helpers_process_any_list#1%
+ {\syst_helpers_process_any_list_indeed\relax}%
+ \syst_helpers_process_any_list}
+
+%D \macros
+%D {processassignlist}
+%D
+%D Is possible to combine an assignment list with one containing keywords.
+%D Assignments are treated accordingly, keywords are treated by \type {\command}.
+%D
+%D \starttyping
+%D \processassignlist[...=...,...=...,...]\commando
+%D \stoptyping
+%D
+%D This command can be integrated in \type {\getparameters}, but we decided best not
+%D to do so.
+
+\unexpanded\def\processassignlist#1[#2]#3%
+ {\def\syst_helpers_process_assign_list_assign[##1=##2=##3]%
+ {\doif{##3}\relax{#3{##1}}}%
+ \def\syst_helpers_process_assign_list_step##1%
+ {\syst_helpers_process_assign_list_assign[##1==\relax]}%
+ \processcommalist[#2]\syst_helpers_process_assign_list_step}
+
+%D \macros
+%D {untextargument
+%D untexcommand}
+%D
+%D When manipulating data(bases) and for instance generating index entries, the next
+%D three macros can be of help:
+%D
+%D \starttyping
+%D \untextargument{...}\to\name
+%D \untexcommand {...}\to\name
+%D \stoptyping
+%D
+%D They remove braces and backslashes and give us something to sort.
+
+\let\m_syst_helpers_untexed\empty
+
+\unexpanded\def\untexsomething
+ {\begingroup
+ \catcode\leftbraceasciicode \ignorecatcode
+ \catcode\rightbraceasciicode\ignorecatcode
+ \escapechar\minusone
+ \syst_helpers_untex_something}
+
+\def\syst_helpers_untex_something#1#2\to#3%
+ {\doglobal#1#2\to\m_syst_helpers_untexed
+ \endgroup
+ \let#3\m_syst_helpers_untexed}
+
+\unexpanded\def\untexargument{\untexsomething\convertargument}
+\unexpanded\def\untexcommand {\untexsomething\convertcommand}
+
+%D \macros
+%D {ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints}
+%D
+%D One characteristic of \POSTSCRIPT\ and \PDF\ is that both used big points (\TEX's
+%D bp). The next macros convert points and scaled points into big points. The magic
+%D factor $72/72.27$ can be found in most \TEX\ related books.
+%D
+%D \starttyping
+%D \ScaledPointsToBigPoints {number} \target
+%D \ScaledPointsToWholeBigPoints {number} \target
+%D \stoptyping
+
+\let\tobigpoints \clf_tobigpoints
+\let\towholebigpoints\clf_towholebigpoints
+
+\unexpanded\def\PointsToBigPoints #1#2{\edef#2{\tobigpoints #1}} % can be avoided
+\unexpanded\def\PointsToWholeBigPoints #1#2{\edef#2{\towholebigpoints#1}} % can be avoided
+\unexpanded\def\ScaledPointsToBigPoints #1#2{\edef#2{\tobigpoints #1\scaledpoint}} % obsolete
+\unexpanded\def\ScaledPointsToWholeBigPoints#1#2{\edef#2{\towholebigpoints#1\scaledpoint}} % obsolete
+
+%D \macros
+%D {PointsToReal}
+%D
+%D Points can be stripped from their suffix by using \type {\withoutpt}. The next
+%D macro enveloppes this macro.
+%D
+%D \starttyping
+%D \PointsToReal {dimension} \target
+%D \stoptyping
+
+\unexpanded\def\PointsToReal#1#2%
+ {\edef#2{\withoutpt\the\dimexpr#1}}
+
+%D \macros
+%D {dontleavehmode}
+%D
+%D Sometimes when we enter a paragraph with some command, the first token gets the
+%D whole first line. We can prevent this by saying:
+%D
+%D \starttyping
+%D \dontleavehmode
+%D \stoptyping
+%D
+%D This command is used in for instance the language module \type {lang-ini}. The
+%D first version was:
+%D
+%D \starttyping
+%D \def\dontleavehmode{\ifhmode\else\ifmmode\else$ $\fi\fi}
+%D \stoptyping
+%D
+%D Next, Taco came with a better alternative (using mathsurround):
+%D
+%D \starttyping
+%D \def\dontleavehmode
+%D {\ifhmode\else \ifmmode\else
+%D {\mathsurround\zeropoint\everymath\emptytoks$ $}%
+%D \fi \fi}
+%D \stoptyping
+%D
+%D And finaly we got the following alternative, one that avoids interfering grouping
+%D at the cost of a box.
+%D
+%D \starttyping
+%D \newbox\b_syst_helpers_dlh
+%D
+%D \unexpanded\def\dontleavehmode
+%D {\ifhmode\else \ifmmode\else
+%D \setbox\b_syst_helpers_dlh\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\b_syst_helpers_dlh
+%D \fi \fi}
+%D \stoptyping
+%D
+%D But, as we run a recent version of \TEX, we can use the new primitive:
+
+\ifdefined\normalquitvmode \let\dontleavehmode\normalquitvmode \fi
+
+%D \macros
+%D {utfupper, utflower, uppercasestring, lowercasestring}
+%D
+%D The names tell what they do:
+%D
+%D \starttyping
+%D \uppercasestring somestring\to\somestring
+%D \lowercasestring somestring\to\somestring
+%D \stoptyping
+%D
+%D The first argument may be a \type{\macro}.
+%D
+%D These macros are sort of obsolete as we never use uppercase this way. But
+%D nevertheless we provide them:
+
+\def\utfupper#1{\clf_upper{#1}} % expandable
+\def\utflower#1{\clf_lower{#1}} % expandable
+
+\unexpanded\def\uppercasestring#1\to#2{\dodoglobal\edef#2{\clf_upper{#1}}}
+\unexpanded\def\lowercasestring#1\to#2{\dodoglobal\edef#2{\clf_lower{#1}}}
+
+%D \macros
+%D {handletokens}
+%D
+%D With the next macro we enter a critical area of macro expansion. What we want is
+%D a macro that looks like:
+%D
+%D \starttyping
+%D \handletokens some tokens\with \somemacro
+%D \stoptyping
+%D
+%D A bonus example:
+%D
+%D \starttyping
+%D \hbox{\handletokens tekst en meer tekst\with\ruledhbox}
+%D
+%D \def\weetikveel#1{\if#1\blankspace\space\else\ruledhbox{#1}\fi}
+%D
+%D \hbox{\handletokens tekst en meer tekst\with\weetikveel}
+%D \stoptyping
+
+%D \macros
+%D {counttoken,counttokens}
+%D
+%D For the few occasions that we want to know the number of specific tokens in a
+%D string, we can use:
+%D
+%D \starttyping
+%D \counttoken token\in string\to \somecount
+%D \counttokens string\to \somecount
+%D \stoptyping
+%D
+%D This macro, that for instance is used in \type {cont-tab}, takes a real counter.
+%D The macro can be preceded by \type {\doglobal}.
+
+\def\syst_helpers_count_token#1% obeys {}
+ {\def\m_syst_string_three{#1}%
+ \ifx\m_syst_string_two\m_syst_string_three \else
+ \ifx\m_syst_string_one\m_syst_string_three
+ \advance\privatescratchcounter\plusone
+ \fi
+ \expandafter\syst_helpers_count_token
+ \fi}
+
+\unexpanded\def\counttoken#1\in#2\to#3%
+ {\privatescratchcounter\zerocount
+ \def\m_syst_string_one{#1}%
+ \def\m_syst_string_two{\end}%
+ \syst_helpers_count_token#2\end
+ \dodoglobal#3\privatescratchcounter}
+
+\unexpanded\def\counttokens#1\to#2%
+ {\privatescratchcounter\zerocount
+ \def\syst_helpers_count_token##1{\advance\privatescratchcounter\plusone}%
+ \handletokens#1\with\syst_helpers_count_token
+ \dodoglobal#2\privatescratchcounter}
+
+%D \macros
+%D {splitofftokens}
+%D
+%D Running this one not always gives the expected results. Consider for instance the
+%D macro for which I originally wrote this token handler.
+
+\unexpanded\def\splitofftokens#1\from#2\to#3% slow but hardly used
+ {\ifnum#1>\zerocount
+ \privatescratchcounter#1\relax
+ \def\syst_helpers_split_off_tokens##1%
+ {\ifnum\privatescratchcounter>\zerocount
+ \advance\privatescratchcounter \minusone
+ \edef#3{#3##1}%
+ \fi}%
+ % \let#3\empty % #3 can be #2, so:
+ \expandafter\let\expandafter#3\expandafter\empty
+ \expandafter\handletokens#2\with\syst_helpers_split_off_tokens
+ \else
+ \edef#3{#2}%
+ \fi}
+
+%D This macro can be called like:
+%D
+%D \startbuffer[example]
+%D \splitofftokens10\from01234567 890123456789\to\test [\test]
+%D \stopbuffer
+%D
+%D up there. The reason for this is not that logical but follows from \TEX's
+%D However, the characters that we expect to find in \type {\test} just don't show
+%D sometimes mysterious way of expanding. Look at this:
+%D
+%D \startbuffer[next]
+%D \def\next{a} \edef\test{\next} [\test]
+%D \let\next=b \edef\test{\test\next} [\test]
+%D \let\next=c \edef\test{\next} [\test]
+%D \let\next=d \edef\test{\test\next} [\test]
+%D \let\next=e \expandafter\edef\expandafter\test\expandafter{\test\next} [\test]
+%D \stopbuffer
+%D
+%D \typebuffer[next]
+%D
+%D Careful reading shows that inside an \type {\edef} macro's that are \type {\let}
+%D are not expanded!
+%D
+%D \unprotect\getbuffer[next]\protect
+%D
+%D That's why we finally end up with a macro that looks ahead by using an
+%D assignment, this time by using \type {\futurelet}, and grabbing an argument as
+%D well. That way we can handle the sentinal, a blank space and grouped tokens.
+
+\unexpanded\def\syst_helpers_handle_tokens % \nexthandledtoken is part of interface
+ {\futurelet\nexthandledtoken\syst_helpers_handle_tokens_indeed}
+
+\def\handletokens#1\with#2%
+ {\gdef\syst_helpers_handle_tokens_command{#2}% permits more complex #2's
+ \syst_helpers_handle_tokens#1\end}
+
+\def\syst_helpers_handle_tokens_indeed
+ {\ifx\nexthandledtoken\blankspace
+ \expandafter\syst_helpers_handle_tokens_indeed_one
+ \orelse\ifx\nexthandledtoken\end
+ \expandafter\gobbletwoarguments % also gobble the \end
+ \else
+ \expandafter\syst_helpers_handle_tokens_indeed_two
+ \fi *}
+
+\def\syst_helpers_handle_tokens_indeed_one * %
+ {\syst_helpers_handle_tokens_command{ }\syst_helpers_handle_tokens}
+
+\def\syst_helpers_handle_tokens_indeed_two *#1%
+ {\syst_helpers_handle_tokens_command{#1}\syst_helpers_handle_tokens}
+
+%D This macro is tested on:
+%D
+%D \def\xxx#1{[#1]}
+%D
+%D \startlines
+%D \handletokens abc\with\xxx
+%D \handletokens a b c\with\xxx
+%D \handletokens a b c\with\xxx
+%D \handletokens a{bc}d\with\xxx
+%D \handletokens a\space bc \with\xxx
+%D \stoplines
+%D
+%D And our previous example shows up as:
+%D
+%D \getbuffer[example]
+
+%D \macros
+%D {iftrialtypesetting, ifvisible}
+%D
+%D The next boolean is at first sight a strange one. Sometimes one does a trial
+%D typesetting run, for instance to determine dimensions. Some mechanisms, like
+%D object inclusion, can fail on such trials. Temporary setting the next boolean to
+%D true, helps a lot. The second boolena can be used to inhibit processing
+%D completely.
+
+\newif\ifvisible \visibletrue
+
+\newtoks\everysettrialtypesetting
+\newtoks\everyresettrialtypesetting
+
+\unexpanded\def\settrialtypesetting {\the\everysettrialtypesetting } % obeys grouping so
+\unexpanded\def\resettrialtypesetting{\the\everyresettrialtypesetting} % this one is seldom needed
+
+\let\iftrialtypesetting\iffalse % so we have no \trialtypesettingtrue|false in mkiv !
+
+\appendtoks \let\iftrialtypesetting\iftrue \to \everysettrialtypesetting
+\appendtoks \let\iftrialtypesetting\iffalse \to \everyresettrialtypesetting
+
+%D \macros
+%D {twodigitrounding}
+%D
+%D When using \type {\special}s or \type {\pdfliteral}s, it sometimes makes sense to
+%D limit the precission. The next macro rounds a real number to two digits. It takes
+%D one argument and only works in \ETEX.
+
+\def\integerrounding #1{\clf_rounded\zerocount\numexpr#1\relax}
+\def\onedigitrounding #1{\clf_rounded\plusone \numexpr#1\relax}
+\def\twodigitrounding #1{\clf_rounded\plustwo \numexpr#1\relax}
+\def\threedigitrounding#1{\clf_rounded\plusthree\numexpr#1\relax}
+
+%D \macros
+%D {processcontent}
+%D
+%D This macro is first used in the tabulation macros.
+%D
+%D \starttyping
+%D \unexpanded\def\starthans%
+%D {\processcontent{stophans}\test{\message{\test}\wait}}
+%D \stoptyping
+
+\unexpanded\def\processcontent#1%
+ {\begingroup\expandafter\syst_helpers_process_content\csname#1\endcsname}
+
+\unexpanded\def\syst_helpers_process_content#1#2#3%
+ {\unexpanded\def\syst_helpers_process_content##1#1%
+ {\endgroup\def#2{##1}#3}%
+ \syst_helpers_process_content}
+
+%D \macros
+%D {dogobblesingleempty, dogobbledoubleempty}
+%D
+%D These two macros savely grab and dispose two arguments.
+
+\def\dogobblesingleempty{\dosingleempty\syst_helpers_gobble_single_empty}
+\def\dogobbledoubleempty{\dodoubleempty\syst_helpers_gobble_double_empty}
+
+\def\syst_helpers_gobble_single_empty [#1]{}
+\def\syst_helpers_gobble_double_empty[#1][#2]{}
+
+\let\gobblesingleempty\dogobblesingleempty % also used
+\let\gobbledoubleempty\dogobbledoubleempty % also used
+
+%D \macros
+%D {setdimensionwithunit, freezedimensionwithunit}
+%D
+%D The next assignments are all valid:
+%D
+%D \starttyping
+%D \setdimensionwithunit\scratchdimen{10} {cm}
+%D \setdimensionwithunit\scratchdimen{10cm}{cm}
+%D \setdimensionwithunit\scratchdimen{10cm}{}
+%D \freezedimensionwithunit\SomeWidth{\textwidth}
+%D \freezedimensionwithunit\SomeDepth{\dp\strutbox}
+%D \stoptyping
+%D
+%D As an alternative for the next macro we can use a global assignment inside a box.
+%D The \type {\empty}'s permits gobbling while preventing spurious \type {\relax}'s.
+
+\unexpanded\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick
+ {\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty}
+
+\unexpanded\def\freezedimensionwithunit#1#2%
+ {\setdimensionwithunit\privatescratchdimen#1{#2}\edef#1{\the\privatescratchdimen}}
+
+%D \macros
+%D {doifsometokselse, doifsometoks}
+%D
+%D Not that fast I guess, but here's a way to test for token registers being empty.
+
+\unexpanded\def\doifelsesometoks#1%
+ {\iftok#1\emptytoks
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\unexpanded\def\doifsometoks#1%
+ {\iftok#1\emptytoks
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifemptytoks#1%
+ {\iftok#1\emptytoks
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\let\doifsometokselse\doifelsesometoks
+
+%D \macros
+%D {startstrictinspectnextcharacter}
+%D
+%D This one is for the bibliography module (still?):
+
+\let\syst_helpers_strict_inspect_next_character[
+
+\def\syst_helpers_strict_inspect_next_character% no user macro !
+ {\ifx\nexttoken[%
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+\unexpanded\def\strictdoifelsenextoptional#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \futurelet\nexttoken\syst_helpers_strict_inspect_next_character}
+
+\let\strictdoifnextoptionalelse\strictdoifelsenextoptional
+
+%D \macros
+%D {gobblespacetokens}
+%D
+%D This macro needs a speed-up!
+
+%\def\gobblespacetokens
+% {\doifnextcharelse\empty\donothing\donothing} % no {}\do\do !
+
+\def\gobblespacetokens
+ {\afterassignment\nexttoken\let\nexttoken=}
+
+%D \macros
+%D {verbatimargument}
+%D
+%D As the name says, this macro converts its argument to a (rather safe) string.
+
+\let\verbatimstring\detokenize
+
+%D These are needed in ordinal number conversions:
+
+\def\lastdigit#1%
+ {\expandafter\thelastdigit\number#1\relax}
+
+\def\thelastdigit#1#2%
+ {\ifx#2\relax#1\else\expandafter\thelastdigit\expandafter#2\fi}
+
+\def\lasttwodigits#1%
+ {\expandafter\thelasttwodigits\expandafter0\number#1\relax}
+
+\def\thelasttwodigits#1#2#3% 0 dig ... \relax
+ {\ifx#3\relax#1#2\else\expandafter\thelasttwodigits\expandafter#2\expandafter#3\fi}
+
+%D \macros
+%D {serializecommalist}
+%D
+%D Concatenate commalists:
+
+\let\syst_helpers_serialize_comma_list_step\relax
+
+\def\syst_helpers_serialize_comma_list_step#1%
+ {\edef\serializedcommalist{\serializedcommalist#1}}
+
+\unexpanded\def\serializecommalist[#1]%
+ {\let\serializedcommalist\empty
+ \processcommacommand[#1]\syst_helpers_serialize_comma_list_step}
+
+%D \macros
+%D {purenumber}
+%D
+%D Sometimes we need control over when \TEX\ stops reading a number, especially in
+%D full expandable macros where using \type {\relax} would lead to disasters.
+%D
+%D \starttyping
+%D \ifodd\purenumber{...}\space ... \else ... \fi
+%D \stoptyping
+%D
+%D Here we use a space as number delimiter in combination with a space- and
+%D relax-less \type {\purenumber}. This macro works ok with \type {\the}, \type
+%D {\number} as well as \ETEX's \type {\numexpr}.
+
+\def\purenumber#1{\expandafter\firstofoneargument\expandafter{\number#1}}
+
+%D \macros
+%D {filterfromvalue}
+%D
+%D \starttyping
+%D \setvalue{xx}{{A}{B}{C}}
+%D
+%D \filterfromvalue{xx}{3}{3}
+%D \filterfromvalue{xx}{3}{2}
+%D \filterfromvalue{xx}{3}{1}
+%D \stoptyping
+%D
+%D An alternative is to store 'max' in the list, say:
+%D
+%D \starttyping
+%D \setvalue{xx}{3{A}{B}{C}}
+%D
+%D \filterfromvalues{3}{xx}{3}
+%D \filterfromvalues{3}{xx}{2}
+%D \filterfromvalues{3}{xx}{1}
+%D \stoptyping
+%D
+%D I'll implement this when I'm in \quotation {writing dirty macros mood}.
+
+\def\dofilterfromstr#1#2% max n % no need to be fast
+ {\expandafter \expandafter \expandafter \csstring
+ \ifcase#1\or \ifcase#2\or
+ \firstofoneargument \else
+ \gobbleoneargument \fi
+ \or \ifcase#2\or
+ \firstoftwoarguments \or
+ \secondoftwoarguments \else
+ \gobbletwoarguments \fi
+ \or \ifcase#2\or
+ \firstofthreearguments \or
+ \secondofthreearguments \or
+ \thirdofthreearguments \else
+ \gobblethreearguments \fi
+ \or \ifcase#2\or
+ \firstoffourarguments \or
+ \secondoffourarguments \or
+ \thirdoffourarguments \or
+ \fourthoffourarguments \else
+ \gobblefourarguments \fi
+ \or \ifcase#2\or
+ \firstoffivearguments \or
+ \secondoffivearguments \or
+ \thirdoffivearguments \or
+ \fourthoffivearguments \or
+ \fifthoffivearguments \else
+ \gobblefivearguments \fi
+ \fi}
+
+\def\filterfromvalue#1#2#3% value max n
+ {\expandafter\doubleexpandafter\csname % we use the fact that an
+ \expandafter\ifx\csname#1\endcsname\relax % undefined cs has become \relax
+ \csstring\gobbleoneargument % which we then gobble here
+ \else
+ \dofilterfromstr{#2}{#3}%
+ \fi
+ \endcsname\csname#1\endcsname}
+
+\def\filterfromnext#1#2% max n {..}{..}{..}{..}
+ {\csname\dofilterfromstr{#1}{#2}\endcsname}
+
+%D \macros
+%D {definemeasure}
+%D
+%D \starttyping
+%D \definemeasure[mywidth][\dimexpr(\textwidth-1cm)]
+%D
+%D ... \measure{mywidth} ...
+%D \stoptyping
+
+\installsystemnamespace{measure}
+
+\unexpanded\def\definemeasure
+ {\dodoubleargument\syst_helpers_define_measure}
+
+\def\syst_helpers_define_measure[#1][#2]%
+ {\expandafter\def\csname\??measure#1\endcsname{#2}}
+
+\unexpanded\def\freezemeasure
+ {\dodoubleargument\syst_helpers_freeze_measure}
+
+\def\syst_helpers_freeze_measure[#1][#2]%
+ {\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}}
+
+\unexpanded\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way
+\unexpanded\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way
+\unexpanded\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+\unexpanded\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+
+\def\measure
+ {\the\measured}
+
+\def\measured#1%
+ %{\dimexpr\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi\relax}
+ {\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+
+% #2 could be omitted, but we want to support spaces
+%
+% \setmeasure {x} {1cm}
+% \setmeasure {xx} {1cm}
+% \setmeasure {xxx}{1cm}
+
+%D \macros
+%D {dividedsize}
+%D
+%D This one can be used inside a measure (used in m4all):
+%D
+%D \starttyping
+%D \definemeasure[columnwidth][\dividedsize\textwidth{1em}{3}]
+%D \stoptyping
+
+\def\dividedsize#1#2#3% size gap n
+ {\dimexpr
+ \ifnum\dimexpr#1\relax>\plusone
+ (\dimexpr#1\relax-\numexpr#3-\plusone\relax\dimexpr#2\relax)/#3\else#1%
+ \fi
+ \relax}
+
+%D \macros
+%D {doifdimensionelse}
+%D
+%D This is a dirty one: we simply append a unit and discard it when needed.
+
+\def\doifelsedimension#1%
+ {\ifchkdim#1\or
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifdimensionelse\doifelsedimension
+
+%D Ok, here's another one, slower but seldom used. This one scans the text.
+%D
+%D \starttabulate[|Tc|Tc|]
+%D \NC pt \NC \doifdimenstringelse {pt}{yes}{no} \NC \NR
+%D \NC 12pt \NC \doifdimenstringelse {-12pt}{yes}{no} \NC \NR
+%D \NC 1pt \NC \doifdimenstringelse {1pt}{yes}{no} \NC \NR
+%D \NC 12pt \NC \doifdimenstringelse {12pt}{yes}{no} \NC \NR
+%D \NC 12.0pt \NC \doifdimenstringelse {12.0pt}{yes}{no} \NC \NR
+%D \NC -.12pt \NC \doifdimenstringelse {-.12pt}{yes}{no} \NC \NR
+%D \NC .12pt \NC \doifdimenstringelse {.12pt}{yes}{no} \NC \NR
+%D \NC -12pt \NC \doifdimenstringelse {-12pt}{yes}{no} \NC \NR
+%D \NC -12.0pt \NC \doifdimenstringelse{-12.0pt}{yes}{no} \NC \NR
+%D \NC big \NC \doifdimenstringelse {big}{yes}{no} \NC \NR
+%D \NC 10 \NC \doifdimenstringelse {10}{yes}{no} \NC \NR
+%D \NC 1 \NC \doifdimenstringelse {1}{yes}{no} \NC \NR
+%D \stoptabulate
+
+\let\doifelsedimenstring\doifelsedimension
+\let\doifdimenstringelse\doifelsedimenstring
+
+%D \macros
+%D {comparedimension,comparedimensioneps}
+%D
+%D This is a dirty one: we simply append a unit and discard it when needed.
+
+\newdimen \roundingeps \roundingeps=10sp
+\newconstant\compresult
+
+\def\comparedimension#1#2%
+ {\compresult
+ \ifdim#1<#2%
+ \zerocount
+ \orelse\ifdim#1<#2%
+ \plusone
+ \else
+ \plustwo
+ \fi}
+
+\def\comparedimensioneps#1#2% todo: use eps feature
+ {\compresult
+ \ifdim\dimexpr#1-#2\relax<\roudingeps
+ \zerocount
+ \orelse\ifdim\dimexpr#2-#1\relax<\roudingeps
+ \zerocount
+ \orelse\ifdim#1<#2%
+ \plusone
+ \else
+ \plustwo
+ \fi}
+
+% pretty ugly but fast
+
+% \copycsname xxx\endcsname\csname ..\endcsname
+
+\unexpanded\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname}
+
+% \letcscsname \crap \csname ..\endcsname
+% \letcsnamecs \csname ..\endcsname\crap
+% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname
+
+\unexpanded\def\letcscsname {\expandafter\let\expandafter}
+\unexpanded\def\letcsnamecs {\expandafter\let}
+\unexpanded\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter}
+
+% another one, add an item to a commalist
+
+\unexpanded\def\addvalue#1#2% cs item
+ {\ifcsname#1\endcsname\else\expandafter\let\csname#1\endcsname\empty\fi
+ \normalexpanded{\noexpand\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}}
+
+\def\unspaced#1%
+ {\syst_helpers_unspaced#1\end}
+
+\def\syst_helpers_unspaced#1%
+ {\ifx#1\end
+ \expandafter\gobbleoneargument
+ \orelse\ifx#1\blankspace
+ % go on
+ \else
+ #1%
+ \fi
+ \syst_helpers_unspaced}
+
+\unexpanded\def\unspaceargument#1\to#2%
+ {\privatescratchcounter\catcode\spaceasciicode
+ \catcode\spaceasciicode\ignorecatcode
+ \scantextokens{\edef#2{#1}}%
+ \catcode\spaceasciicode\privatescratchcounter}
+
+\unexpanded\def\unspaceafter#1#2%
+ {\unspaceargument#2\to\ascii
+ \expandafter#1\expandafter{\ascii}}
+
+% sometimes handy:
+
+\unexpanded\def\doifelsehasspace#1%
+ {\edef\m_syst_string_one{#1}%
+ \normalexpanded{\syst_helpers_if_has_space_else#1\space}\empty\relax}
+
+\let\doifhasspaceelse\doifelsehasspace
+
+\unexpanded\def\syst_helpers_if_has_space_else#1 #2#3\relax % \space\empty\relax
+ {\ifx\m_syst_string_one\space
+ \expandafter\firstoftwoarguments
+ \orelse\ifx#2\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+% this will replace loadfile once and alike !!! todo
+
+\installsystemnamespace{flag}
+
+\unexpanded\def\setflag #1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\zerocount}
+\unexpanded\def\resetflag#1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\plusone}
+
+\def\flag#1{\csname\??flag#1\endcsname}
+
+\def\doifelseflagged#1%
+ {\expandafter\ifx\csname\??flag#1\endcsname\relax
+ \expandafter\secondoftwoarguments
+ \orelse\ifcase\csname\??flag#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifflaggedelse\doifelseflagged
+
+\def\doifnotflagged#1%
+ {\expandafter\ifx\csname\??flag#1\endcsname\relax
+ \expandafter\firstofoneargument
+ \orelse\ifcase\csname\??flag#1\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey
+ {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter{\csname#1#5\endcsname}}
+
+\def\syst_helpers_if_non_zero_positive_else#1#2\end % #3#4%
+ {\ifx#1\relax
+ \ifcase\privatescratchcounter
+ \endgroup
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \endgroup
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \endgroup
+ \expandafter\secondoftwoarguments
+ \fi}
+
+% used ?
+
+\def\doifelsenonzeropositive#1%
+ {\begingroup\afterassignment\syst_helpers_if_non_zero_positive_else\privatescratchcounter=0#1\relax\empty\end}
+
+\let\doifnonzeropositiveelse\doifelsenonzeropositive
+
+% here ?
+
+\unexpanded\def\dosetrawvalue #1#2#3{\expandafter \def\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawevalue#1#2#3{\expandafter\edef\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawgvalue#1#2#3{\expandafter\gdef\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawxvalue#1#2#3{\expandafter\xdef\csname#1#2\endcsname{#3}}
+
+\unexpanded\def\getrawparameters {\dogetparameters\dosetrawvalue }
+\unexpanded\def\getraweparameters {\dogetparameters\dosetrawevalue}
+\unexpanded\def\getrawgparameters {\dogetparameters\dosetrawgvalue}
+\unexpanded\def\getrawxparameters {\dogetparameters\dosetrawxvalue}
+
+\unexpanded\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete
+
+%D Sort of obsolete:
+
+\newcount\c_syst_helpers_mod
+
+\unexpanded\def\dosetmodulo#1#2#3%
+ {\c_syst_helpers_mod#1\divide\c_syst_helpers_mod#2\multiply\c_syst_helpers_mod#2%
+ #3#1\advance#3-\c_syst_helpers_mod}
+
+\unexpanded\def\dosetdivision#1#2#3%
+ {#3#1\divide#3 #2\relax}
+
+\unexpanded\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}}
+\unexpanded\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}}
+
+\def\syst_helpers_unprotected#1\par
+ {#1\protect}
+
+\unexpanded\def\unprotected
+ {\unprotect
+ \syst_helpers_unprotected}
+
+\let\resettimer \clf_resettimer
+\let\elapsedtime \clf_elapsedtime
+\let\elapsedseconds \elapsedtime
+
+\newcount\c_syst_helpers_test_feature_n
+\newcount\c_syst_helpers_test_feature_m
+
+\def\currentfeaturetest{\number\c_syst_helpers_test_feature_n}
+
+\unexpanded\def\testfeature#1#2%
+ {\c_syst_helpers_test_feature_m#1\relax
+ \def\syst_helpers_test_feature_yes
+ {\advance\c_syst_helpers_test_feature_n\plusone
+ \ifnum\c_syst_helpers_test_feature_n>\c_syst_helpers_test_feature_m\else
+ #2\expandafter\syst_helpers_test_feature_yes
+ \fi}%
+ \def\syst_helpers_test_feature_nop
+ {\advance\c_syst_helpers_test_feature_n\plusone
+ \ifnum\c_syst_helpers_test_feature_n>\c_syst_helpers_test_feature_m\else
+ \expandafter\syst_helpers_test_feature_nop
+ \fi}%
+ \retestfeature}
+
+\unexpanded\def\retestfeature % timer support is new per 10/5/2005
+ {\bgroup
+ \ifcase\interactionmode\let\wait\relax\fi
+ \clf_resettimer
+ \c_syst_helpers_test_feature_n\zerocount
+ \syst_helpers_test_feature_nop
+ \clf_benchmarktimer
+ \writestatus\m!system{starting feature test (n=\number\c_syst_helpers_test_feature_m)}\wait
+ \c_syst_helpers_test_feature_n\zerocount
+ \syst_helpers_test_feature_yes
+ \writestatus\m!system{\number\c_syst_helpers_test_feature_m\space feature tests done (\elapsedseconds s)}%
+ \wait
+ \egroup}
+
+\unexpanded\def\showtimer#1%
+ {\writestatus{runtime}{\elapsedseconds\space s / #1}}
+
+\unexpanded\def\testfeatureonce#1#2%
+ {\begingroup
+ \let\wait\relax
+ \testfeature{#1}{#2}%
+ \endgroup}
+
+%D \macros
+%D {freezedimenmacro}
+%D
+%D This macro is use as:
+%D
+%D \starttyping
+%D \freezedimenmacro\leftmargindistance
+%D \stoptyping
+
+\unexpanded\def\freezedimenmacro#1%
+ {\edef#1{\the\dimexpr#1}}
+
+%D The next macro negates a macro (dimension or number, or actually, whatever. It's
+%D a typical example of \type {\if} usage:
+%D
+%D \starttyping
+%D \if-\whatever \else-\whatever\fi => else => -whatever
+%D \if--\whatever\else-\whatever\fi => then => whatever
+%D \stoptyping
+
+\def\negated#1{\if-#1\else-#1\fi} % does only work in macros or text
+
+\def\gobbleassigndimen#1\\{}
+
+\def\assigndimen#1#2%
+ {\afterassignment\gobbleassigndimen#1=#2\zeropoint\\}
+
+\unexpanded\def\appended#1#2#3{\expandafter#1\expandafter#2\expandafter{#2#3}}
+\unexpanded\def\appendvalue #1{\expandafter\appended\expandafter \def\csname#1\endcsname}
+\unexpanded\def\appendgvalue#1{\expandafter\appended\expandafter\gdef\csname#1\endcsname}
+
+\unexpanded\def\prepended#1#2#3%
+ {\t_syst_helpers_scratch{#3}%
+ \expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter#2\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_syst_helpers_scratch#2}}
+
+\unexpanded\def\prependvalue #1{\expandafter\prepended\expandafter \def\csname#1\endcsname}
+\unexpanded\def\prependgvalue#1{\expandafter\prepended\expandafter\gdef\csname#1\endcsname}
+
+%D \macros
+%D {dowithrange}
+%D
+%D This one is for Mojca Miklavec, who made me aware of the fact that \type
+%D {page-imp.tex} was not the best place to hide it.
+%D
+%D \startbuffer
+%D \def\DoSomething#1{ [item #1] }
+%D
+%D \processranges[1,4:5]\DoSomething \par
+%D \dowithrange {1,4:5}\DoSomething \par
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+\def\syst_helpers_with_range#1%
+ {\splitstring#1\at:\to\m_syst_helpers_range_from\and\m_syst_helpers_range_to
+ \ifx\m_syst_helpers_range_to\empty\let\m_syst_helpers_range_to\m_syst_helpers_range_from\fi
+ \dostepwiserecurse\m_syst_helpers_range_from\m_syst_helpers_range_to\plusone{\m_helpers_range_action{##1}}}%
+
+\unexpanded\def\processranges[#1]#2% #1= n:m,p,q:r
+ {\def\m_helpers_range_action{#2}%
+ \processcommacommand[#1]\syst_helpers_with_range}
+
+\unexpanded\def\dowithrange#1#2%
+ {\def\m_helpers_range_action{#2}%
+ \processcommacommand[#1]\syst_helpers_with_range}
+
+% \def\DoSomething#1{ [item #1] }
+% \dowithrange[1,4:5]\DoSomething
+
+%D \macros
+%D {ignoreimplicitspaces}
+%D
+%D \startbuffer
+%D \def\whatever[#1]{\expanded{\definedfont[#1 at 12pt]}\ignorespaces}
+%D {a\whatever[Serif]b a\whatever[Serif] b a\whatever[Serif]\space b}
+%D \def\whatever[#1]{\expanded{\definedfont[#1 at 12pt]}\ignoreimplicitspaces}
+%D {a\whatever[Serif]b a\whatever[Serif] b a\whatever[Serif]\space b}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\ignoreimplicitspaces
+ {\doifelsenextchar\relax\relax\relax}
+
+%D \macros
+%D {processwords}
+%D
+%D Not that sophisticated but sometimes users (like in metafun).
+
+\def\syst_helpers_process_word#1 #2\_e_o_w_
+ {\doifsomething{#1}{\processword{#1} \syst_helpers_process_word#2 \_e_o_w_}}
+
+\def\processwords#1%
+ {\syst_helpers_process_word#1 \_e_o_w_}% no \unskip
+
+\let\processword\relax
+
+%D \macros
+%D {startnointerference}
+%D
+%D \starttyping
+%D \startnointerference
+%D all kind of code
+%D \stopnointerference
+%D \stoptyping
+
+\newbox\b_syst_helpers_no_interference
+
+\unexpanded\def\startnointerference % not even grouped !
+ {\setbox\b_syst_helpers_no_interference\vbox
+ \bgroup}
+
+\unexpanded\def\stopnointerference
+ {\egroup
+ \setbox\b_syst_helpers_no_interference\emptybox}
+
+%D A variant for \type {\executeifdefined}:
+
+\def\expandcheckedcsname#1#2% #2 is often a \xxxparameter so let's expand it once
+ {\normalexpanded{\noexpand\syst_helpers_expand_checked_csname{#1}{#2}}}
+
+\def\syst_helpers_expand_checked_csname#1#2#3%
+ {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
+
+%D Signal. Some fonts have a char0 rendering so we need to make sure that it is not
+%D set in the font! (This will be overloaded)
+
+\unexpanded\def\signalcharacter{\char\zerocount} % \zwj
+
+%D A few secial variants of commands defined here. Some more will be moved here (e.g.
+%D from table modules.
+
+\def\dodirectdoubleempty#1#2% used in math (lookahead issues)
+ {\ifx#2[%
+ \expandafter\syst_helpers_direct_double_empty_one_yes
+ \else
+ \expandafter\syst_helpers_direct_double_empty_one_nop
+ \fi#1#2}
+
+\def\syst_helpers_direct_double_empty_one_yes#1[#2]#3%
+ {\ifx#3[\else\expandafter\syst_helpers_direct_double_empty_two_nop\fi#1[#2]#3}
+
+\def\syst_helpers_direct_double_empty_one_nop#1{#1[][]}
+\def\syst_helpers_direct_double_empty_two_nop#1[#2]{#1[#2][]}
+
+%D Used in math definitions (in an \type {\edef}):
+
+%D \startbuffer
+%D [\docheckedpair{}]
+%D [\docheckedpair{a}]
+%D [\docheckedpair{a,b}]
+%D [\docheckedpair{a,b,c}]
+%D \stopbuffer
+%D
+%D \typebuffer \startlines \getbuffer \stoplines
+
+\def\docheckedpair#1%
+ {\syst_helpers_checked_pair#1,,\_o_e_p_}
+
+\def\syst_helpers_checked_pair#1,#2,#3\_o_e_p_
+ {#1,#2}
+
+%D Here are some nasty helpers. They can be used to fill often expanded token
+%D lists efficiently (see tabulate for an example).
+
+\def\constantnumber#1%
+ {\ifcase#1\zerocount
+ \or \plusone
+ \or \plustwo
+ \or \plusthree
+ \or \plusfour
+ \or \plusfive
+ \or \plussix
+ \or \plusseven
+ \or \pluseight
+ \or \plusnine
+ \or \plusten
+ \else \number#1\relax\fi}
+
+\def\constantnumberargument#1%
+ {\ifcase#1\zerocount
+ \or \plusone
+ \or \plustwo
+ \or \plusthree
+ \or \plusfour
+ \or \plusfive
+ \or \plussix
+ \or \plusseven
+ \or \pluseight
+ \or \plusnine
+ \or \plusten
+ \else {\number#1}\fi}
+
+\def\constantdimen#1%
+ {\ifdim#1=\zeropoint
+ \zeropoint
+ \else
+ \the#1\relax
+ \fi}
+
+\def\constantdimenargument#1%
+ {\ifdim#1=\zeropoint
+ \zeropoint
+ \else
+ {\the#1}%
+ \fi}
+
+\def\constantemptyargument#1%
+ {\ifx#1\empty
+ \noexpand\empty
+ \else
+ {#1}%
+ \fi}
+
+%D \macros
+%D {getsubstring}
+%D \startbuffer
+%D
+%D \getsubstring{4}{}{Who Wants This}
+%D \getsubstring{4}{9}{Who Wants This}
+%D \getsubstring{9}{-2}{Who Wants This}
+%D \getsubstring{1}{5}{Who Wants This}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+% expandable:
+
+\def\getsubstring#1#2#3{\clf_getsubstring{#3}{#1}{#2}}
+
+%D Other dimensions than pt (used in mb-mp)
+
+\def\converteddimen#1#2{\clf_converteddimen\dimexpr#1\relax{#2}}
+
+%D Maybe (looks ugly):
+%D
+%D \starttyping
+%D \doifcase {foo}
+%D {bar} {BAR}
+%D {foo} {FOO}
+%D {default} {DEFAULT}
+%D
+%D \doifcase {foo}
+%D {bar} {BAR}
+%D {foo} {\doifcase {bar}
+%D {bar} {BAR}
+%D {foo} {FOO}
+%D {default} {DEFAULT}
+%D }
+%D {default} {DEFAULT}
+%D \stoptyping
+
+% \doifcase {\btxfoundname{author}}
+% {author} {\btxflush{author}}
+% {editor} {\texdefinition{btx:apa:editor-or-editors}}
+% {title} {\texdefinition{btx:apa:title-subtitle-type}}
+% {default} {\btxflush{author}}
+
+% \unexpanded\def\doifcase#1%
+% {\edef\m_case_asked{#1}%
+% \syst_aux_case}
+%
+% \def\syst_aux_case#1%
+% {\edef\m_case_temp{#1}%
+% \ifx\m_case_temp\m_case_asked
+% \expandafter\syst_aux_case_yes
+% \orelse\ifx\m_case_temp\s!default
+% \expandafter\firstofoneargument
+% \else
+% \expandafter\syst_aux_case_nop
+% \fi}
+%
+% \def\syst_aux_skip#1#2%
+% {\edef\m_case_temp{#1}%
+% \ifx\m_case_temp\s!default
+% \expandafter\syst_aux_done
+% \else
+% \expandafter\syst_aux_skip
+% \fi}
+%
+% \def\syst_aux_case_yes#1%
+% {\def\syst_aux_done{#1}%
+% \syst_aux_skip}
+%
+% \def\syst_aux_case_nop#1%
+% {\syst_aux_case}
+
+%D \macros
+%D {ntimes}
+%D
+%D some repetition:
+%D
+%D \startbuffer
+%D \ntimes{*}{20}
+%D \stopbuffer
+%D
+%D \typebuffer \blank gives: \getbuffer \blank
+%D
+%D This is not real fast but quite okay:
+
+%def\ntimes#1#2{\ifnum#2>\zerocount#1\ntimes{#1}{\numexpr#2-\plusone\relax}\fi} % 1.72
+\def\ntimes#1#2{\clf_ntimes{#1}\numexpr#2\relax} % 0.33
+
+%D Experiment (sometimes looks nicer in code):
+
+\unexpanded\def\sameargumentscondition#1#2%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two}
+
+\unexpanded\def\emptyargumentcondition#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv
index 4be622d48..013f1106f 100644
--- a/tex/context/base/mkiv/syst-ini.mkiv
+++ b/tex/context/base/mkiv/syst-ini.mkiv
@@ -570,9 +570,7 @@
\newif\ifdone
\newif\iffound
-%D Potential primitive in \LUATEX:
-
-\ifdefined\htdp \else \def\htdp#1{\dimexpr\ht#1+\dp#1\relax} \fi
+\def\htdp#1{\dimexpr\ht#1+\dp#1\relax}
%D A few shortcuts:
diff --git a/tex/context/base/mkiv/syst-ini.mkxl b/tex/context/base/mkiv/syst-ini.mkxl
new file mode 100644
index 000000000..8f89d9221
--- /dev/null
+++ b/tex/context/base/mkiv/syst-ini.mkxl
@@ -0,0 +1,1075 @@
+%D \module
+%D [ file=syst-ini,
+%D version=2008.11.04, % 2001.11.16, % 1999.03.17, % an oldie: 1995.10.10
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Bootstrapping \TEX,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D We used to load plain \TEX\ in a special way, but redefining a couple of
+%D primitives so that for instance font loading was ignored. For those interested,
+%D this loader is found in \type {syst-tex.tex}. Some of the comment's are Don
+%D Knuths and more of it can be found in the plain \TEX\ format.
+%D
+%D Characters can have special states, that can be triggered by setting their
+%D category coded. Some are preset, others are to be set as soon as possible,
+%D otherwise we cannot define any useful macros.
+%D
+%D First we define a bunch of constants. Normally we would \type {\setconstant}
+%D but we're prestine and have no macros defined yet. Abstraction also makes it
+%D possible to avoid the \type {^^} in the input.
+
+\chardef\escapecatcode 0
+\chardef\begingroupcatcode 1
+\chardef\endgroupcatcode 2
+\chardef\mathshiftcatcode 3
+\chardef\alignmentcatcode 4
+\chardef\endoflinecatcode 5
+\chardef\parametercatcode 6
+\chardef\superscriptcatcode 7
+\chardef\subscriptcatcode 8
+\chardef\ignorecatcode 9
+\chardef\spacecatcode 10
+\chardef\lettercatcode 11
+\chardef\othercatcode 12 % finally obsolete: \let\other \othercatcode
+\chardef\activecatcode 13 % finally obsolete: \let\active\activecatcode
+\chardef\commentcatcode 14
+\chardef\invalidcatcode 15
+
+%chardef\zeroasciicode 0
+\chardef\tabasciicode 9
+\chardef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
+\chardef\formfeedasciicode 12
+\chardef\endoflineasciicode 13 % somewhat messy but this can be the active \par
+\chardef\endoffileasciicode 26
+\chardef\spaceasciicode 32
+\chardef\exclamationmarkasciicode 33 % ! used in namespace protection
+\chardef\doublequoteasciicode 34 % "
+\chardef\hashasciicode 35
+\chardef\dollarasciicode 36
+\chardef\commentasciicode 37
+\chardef\ampersandasciicode 38
+\chardef\singlequoteasciicode 39 % '
+\chardef\primeasciicode 39 % '
+\chardef\leftparentasciicode 40
+\chardef\rightparentasciicode 41
+\chardef\hyphenasciicode 45
+\chardef\forwardslashasciicode 47 % /
+\chardef\colonasciicode 58
+\chardef\lessthanasciicode 60 % < used as alternative verbatim {
+\chardef\morethanasciicode 62 % > used as alternative verbatim }
+\chardef\questionmarkasciicode 63 % ? used in namespace protection
+\chardef\atsignasciicode 64 % @ used in namespace protection
+\chardef\backslashasciicode 92 % `\\
+\chardef\circumflexasciicode 94
+\chardef\underscoreasciicode 95
+\chardef\leftbraceasciicode 123 % `\{
+\chardef\barasciicode 124 % `\|
+\chardef\rightbraceasciicode 125 % `\}
+\chardef\tildeasciicode 126 % `\~
+\chardef\delasciicode 127
+
+%catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored
+\catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space
+\catcode\formfeedasciicode \activecatcode % `\^^L ascii form-feed (active, set later)
+%catcode\endoflineasciicode \endoflinecatcode % `\^^M ascii return is end-line
+\catcode\endoffileasciicode \ignorecatcode % `\^^Z endoffile (ignored in ConTeXt)
+%catcode\spaceasciicode \spacecatcode % `\ ascii space is blank space
+\catcode\hashasciicode \parametercatcode % `\# hash mark is macro parameter character
+\catcode\dollarasciicode \mathshiftcatcode % `\$ dollar sign is math shift
+%catcode\commentasciicode \commentcatcode % `\% percent sign is comment character
+\catcode\ampersandasciicode \alignmentcatcode % `\& ampersand is alignment tab
+%catcode\backslashasciicode \escapecatcode % `\\ backslash is TeX escape character
+\catcode\circumflexasciicode \superscriptcatcode % `\^ circumflex and uparrow are for superscripts
+\catcode\underscoreasciicode \subscriptcatcode % `\_ underline and downarrow are for subscripts
+\catcode\leftbraceasciicode \begingroupcatcode % `\{ left brace is begin-group character
+\catcode\rightbraceasciicode \endgroupcatcode % `\} right brace is end-group character
+\catcode\tildeasciicode \activecatcode % `\~ tilde is active
+%catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid
+
+\chardef\statuswrite 128
+
+%D Initialization of primitives.
+
+\directlua {
+ local baseprimitives = tex.extraprimitives("core","tex")
+ local moreprimitives = tex.extraprimitives("etex","luatex")
+
+ tex.enableprimitives("",moreprimitives)
+
+ tex.enableprimitives("normal",baseprimitives)
+ tex.enableprimitives("normal",moreprimitives)
+
+ function tex.enableprimitives() end
+}
+
+\def\space{ }
+\def\empty{}
+
+\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed
+\letcharcode \tildeasciicode \ % tilde
+\letcharcode \spaceasciicode \space % space
+
+\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab
+\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed
+\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return
+
+%D For now:
+
+\def\gobbleoneargument#1{} % will be defined later on anyway
+
+%D First we define a simplified version of the \CONTEXT\ protection mechanism.
+%D Later we will implement a better variant.
+
+\def\unprotect
+ {\edef\protect
+ {\catcode\atsignasciicode \the\catcode\atsignasciicode \relax
+ \catcode\exclamationmarkasciicode\the\catcode\exclamationmarkasciicode\relax
+ \catcode\questionmarkasciicode \the\catcode\questionmarkasciicode \relax
+ \catcode\underscoreasciicode \the\catcode\underscoreasciicode \relax
+ \let\protect\relax}%
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\underscoreasciicode \lettercatcode}
+
+\let\protect\relax
+
+\unprotect
+
+%D Some pretty important definitions:
+
+\let\bgroup={
+\let\egroup=}
+
+%D \macros
+%D {normalbgroup,normalgroup}
+%D
+%D No comment.
+
+%D Allocation of registers is done slightly different than in plain \TEX. First of
+%D all we use different reserved counters. We also don't implement a family handler
+%D because users are not supposed to implement their own math. We reserve the lowest
+%D 31 registers for scratch purposes. Keep in mind that in the core engine some
+%D registers are reserved: counters 0 upto 9, and counter 255.
+%D
+%D As with plain \TEX\ we recommend that macro designers always use \type {\global}
+%D assignments with respect to registers numbered 1, 3, 5 \unknown\ 31, and always
+%D non||\type {\global} assignments with respect to registers 0, 2, 4, \unknown\ 30.
+%D This will prevent \quote {save stack buildup} that might otherwise occur.
+%D
+%D We reserve some registers for special (management) purposes:
+
+% 0 - 20 : scratch
+% 21 - 127 : internal
+% 128 - 254 : inserts
+% 255 : page
+% 256 - : user
+
+\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change
+\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 32767
+\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = -1
+\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 16
+\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0
+\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 255
+\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128
+\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254
+\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128
+\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255
+\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private
+\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0
+\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 127
+
+\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read
+\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write
+\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context
+\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert
+\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context
+\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context
+
+\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end
+\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end
+
+\countdef \zerocount = 120 \zerocount = 0
+\countdef \plusone = 121 \plusone = 1
+\countdef \minusone = 122 \minusone = -1
+
+\countdef \normalpagebox = 127 \normalpagebox = 255 % hardcoded in pdftex/xetex
+
+% Only to be used by developers in very special cases!
+
+% \def\lastallocatedcount {\the\c_syst_last_allocated_count}
+% \def\lastallocateddimen {\the\c_syst_last_allocated_dimen}
+% \def\lastallocatedskip {\the\c_syst_last_allocated_skip}
+% \def\lastallocatedmuskip {\the\c_syst_last_allocated_muskip}
+% \def\lastallocatedbox {\the\c_syst_last_allocated_dimen}
+% \def\lastallocatedtoks {\the\c_syst_last_allocated_toks}
+% \def\lastallocatedattribute{\the\c_syst_last_allocated_attribute}
+
+% A few traditional allocations (these might go):
+
+\countdef \count@ 255 % hm, used in \newif .. todo: replace it there
+\dimendef \dimen@ 0
+\dimendef \dimen@i 1 % global only
+\dimendef \dimen@ii 2
+
+%D So, effectively we start allocating from 256 and upwards. The inserts sit in the
+%D range 128 upto 254. Page numbers use the counters 0 upto 9 and the pagebox is
+%D 255. Users can use the scratch registers upto 31 without problem but all others
+%D are reserved.
+
+\let\wlog\gobbleoneargument % Let's get rid of this one.
+
+%D The allocators share a common helper macro.
+
+\normalprotected\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register}
+\normalprotected\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register}
+\normalprotected\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register}
+\normalprotected\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register}
+\normalprotected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \mathchardef\c_syst_max_allocated_register}
+\normalprotected\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register}
+\normalprotected\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \chardef \c_syst_max_allocated_read}
+\normalprotected\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \chardef \c_syst_max_allocated_write}
+\normalprotected\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \mathchardef\c_syst_max_allocated_register}
+\normalprotected\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert}
+
+%D We don't need these in \CONTEXT:
+
+\normalprotected\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\chardef \c_syst_max_allocated_language}
+\normalprotected\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \chardef \c_syst_max_allocated_family}
+
+\let\newfam\newfamily
+
+\firstvalidlanguage\plusone
+
+% Watch out, for the moment we disable the check for already being defined
+% later we will revert this but first all chardefs must be replaced.
+
+\normalprotected\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1}
+\normalprotected\def\setnewconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number
+\normalprotected\def\setconstant {} % dummy, no checking, so it warns
+\normalprotected\def\setconstantvalue#1#2{\csname#1\endcsname\numexpr#2\relax}
+
+% maybe setconstant with check
+
+% %D The next definitions are really needed (in \CONTEXT):
+
+\newlinechar\newlineasciicode \edef\outputnewlinechar{\Uchar\newlineasciicode} % {^^J}
+
+%D One reason to start high with allocation is that it permits us to allocate
+%D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a
+%D continuous range of boxes. It also permits us to do a proper upward allocation
+%D for inserts. The current code evolved from code that dealt with older engines but
+%D as all engines now provide many registers we removed all traces.
+
+\ifdefined\writestatus \else
+ %\normalprotected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}}
+ \normalprotected\def\writestatus#1#2{\message{#1: #2}}
+\fi
+
+\def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name
+ {\ifnum#1<#4\relax
+ \global\advance#1\plusone
+ \global#3#5=#1\relax
+ \else
+ \writestatus{warning}{no room for \string#2\space \string#5\space (max: \number#4)}%
+ \fi}
+
+\def\syst_basics_allocate_nop#1#2#3#4#5% last class method max name
+ {\writestatus{warning}{\string#2 \string#5 is already defined (\string\relax\space it first)}}
+
+\def\syst_basics_allocate#1#2#3#4#5% last class method max name
+ {\ifx#5\undefined
+ \expandafter\syst_basics_allocate_yes
+ \else\ifx#5\relax
+ \expandafter\expandafter\expandafter\syst_basics_allocate_yes
+ \else
+ \expandafter\expandafter\expandafter\syst_basics_allocate_nop
+ \fi\fi
+ #1#2#3#4#5}
+
+%D Since the number of chars exceed 256 now, we can use \type {\chardef} instead of
+%D the more limited \type {\mathchardef}.
+
+\normalprotected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register}
+\normalprotected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register}
+
+%D Attributes are something very \LUATEX. In \CONTEXT\ you are not supposed to use
+%D the attributes directly but always allocate then first. For instance attribute~0
+%D is reserved for special purposes (this might change). Attributes in the range
+%D 128-1023 are private and should not be touched.
+
+\let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone
+
+\normalprotected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register}
+
+%D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force
+%D strings instead of tokens that take more memory. It's a trick to trick to force
+%D strings. This macro is never used in \CONTEXT.
+
+%normalprotected\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
+\normalprotected\def\newhelp#1#2{\newtoks#1#1\expandafter{\detokenize{#2}}}
+
+%D \macros
+%D {scratchcounter,
+%D scratchdimen,scratchskip,scratchmuskip,
+%D scratchbox,
+%D scratchtoks}
+%D
+%D We now define a few scratch registers, so that successive loads at least have
+%D some available. The private ones are used in cases where we don't want to
+%D intrude on normal scratch ones.
+
+\newcount \scratchcounter \newcount \globalscratchcounter \newcount \privatescratchcounter
+\newdimen \scratchdimen \newdimen \globalscratchdimen \newdimen \privatescratchdimen
+\newskip \scratchskip \newskip \globalscratchskip \newskip \privatescratchskip
+\newmuskip\scratchmuskip \newmuskip\globalscratchmuskip \newmuskip\privatescratchmuskip
+\newtoks \scratchtoks \newtoks \globalscratchtoks \newtoks \privatescratchtoks
+\newbox \scratchbox \newbox \globalscratchbox \newbox \privatescratchbox
+
+\newcount\scratchcounterone \newcount\scratchcountertwo \newcount\scratchcounterthree
+\newdimen \scratchdimenone \newdimen \scratchdimentwo \newdimen \scratchdimenthree
+\newskip \scratchskipone \newskip \scratchskiptwo \newskip \scratchskipthree
+\newmuskip\scratchmuskipone \newmuskip\scratchmuskiptwo \newmuskip\scratchmuskipthree
+\newtoks \scratchtoksone \newtoks \scratchtokstwo \newtoks \scratchtoksthree
+\newbox \scratchboxone \newbox \scratchboxtwo \newbox \scratchboxthree
+
+\newcount\scratchcounterfour \newcount\scratchcounterfive \newcount\scratchcountersix
+\newdimen \scratchdimenfour \newdimen \scratchdimenfive \newdimen \scratchdimensix
+\newskip \scratchskipfour \newskip \scratchskipfive \newskip \scratchskipsix
+\newmuskip\scratchmuskipfour \newmuskip\scratchmuskipfive \newmuskip\scratchmuskipsix
+\newtoks \scratchtoksfour \newtoks \scratchtoksfive \newtoks \scratchtokssix
+\newbox \scratchboxfour \newbox \scratchboxfive \newbox \scratchboxsix
+
+\newcount\globalscratchcounterone
+\newcount\globalscratchcountertwo
+\newcount\globalscratchcounterthree
+
+%D \macros
+%D {tempstring}
+
+\let\tempstring\empty
+
+%D \macros
+%D {scratchwidth, scratchheight, scratchdepth, scratchoffset, scratchdistance}
+%D
+%D A few more scratch dimensions:
+
+\newdimen\scratchwidth
+\newdimen\scratchheight
+\newdimen\scratchdepth
+
+\newdimen\scratchoffset
+\newdimen\scratchleftoffset
+\newdimen\scratchrightoffset
+\newdimen\scratchtopoffset
+\newdimen\scratchbottomoffset
+
+\newdimen\scratchdistance
+
+\newdimen\scratchhsize
+\newdimen\scratchvsize
+
+\newdimen\scratchxoffset
+\newdimen\scratchyoffset
+\newdimen\scratchhoffset
+\newdimen\scratchvoffset
+
+\newdimen\scratchxposition
+\newdimen\scratchyposition
+
+\newcount\scratchnx
+\newcount\scratchny
+
+\newcount\scratchmx
+\newcount\scratchmy
+
+\newcount\scratchmin
+\newcount\scratchmax
+
+\newcount\scratchunicode
+
+\newdimen\scratchleftskip
+\newdimen\scratchrightskip
+\newdimen\scratchtopskip
+\newdimen\scratchbottomskip
+
+%D More allocations:
+
+\newskip \zeroskip \zeroskip 0pt plus 0pt minus 0pt
+\newdimen \zeropoint \zeropoint 0pt
+\newdimen \onepoint \onepoint 1pt
+\newdimen \halfapoint \halfapoint 0.5pt
+\newdimen \maxdimen \maxdimen 16383.99999pt % 1073741823sp
+\newcount \maxcount \maxcount 2147483647
+\newdimen \onebasepoint \onebasepoint 1bp
+\newdimen \scaledpoint \scaledpoint 1sp
+\newdimen \thousandpoint \thousandpoint 1000pt
+\newmuskip\zeromuskip \zeromuskip 0mu
+\newmuskip\onemuskip \onemuskip 1mu
+
+\newmuskip\muquad \muquad 18mu
+
+\let\points \onepoint
+\let\halfpoint\halfapoint
+
+\newtoks \emptytoks
+
+%D And even more: (todo: countdefs 60+)
+
+%newcount\minusone \minusone -1
+\newcount\minustwo \minustwo -2
+%chardef \zerocount 0
+%chardef \plusone 1
+\chardef \plustwo 2
+\chardef \plusthree 3
+\chardef \plusfour 4
+\chardef \plusfive 5
+\chardef \plussix 6
+\chardef \plusseven 7
+\chardef \pluseight 8
+\chardef \plusnine 9
+\chardef \plusten 10
+\chardef \plussixteen 16
+\chardef \plusfifty 50
+\chardef \plushundred 100
+\chardef \plusonehundred 100
+\chardef \plustwohundred 200
+\chardef \plusfivehundred 500
+\chardef \pluscxxvii 127
+\chardef \pluscxxviii 128
+\chardef \pluscclv 255
+\chardef \pluscclvi 256
+\chardef \plusthousand 1000
+\chardef \plustenthousand 10000
+\chardef \plustwentythousand 20000
+\chardef \medcard 32768
+\chardef \maxcard 65536 % pdftex has less mathchars
+\chardef \maxcardminusone 65535
+
+%D \macros
+%D {doubleexpandafter,tripleexpandafter,expanded,startexpanded}
+%D
+%D A few handy shortcuts
+
+\let\singleexpandafter \expandafter
+\def\doubleexpandafter{\expandafter\expandafter\expandafter}
+\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter}
+
+%D We prefer the more readable variant than in plain \TEX. User should only
+%D use \type {\emptybox}:
+
+\newbox\voidbox % public
+
+\let\normalhbox\hbox
+\let\normalvbox\vbox
+
+\def\unvoidbox{\unhbox\voidbox}
+\def\emptybox {\box \voidbox} % used in initializations so no attributes
+\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes
+\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes
+
+\let\leavevmode\unvoidbox % we prefer to use \dontleavehmode
+
+%D \macros
+%D {dontcomplain}
+%D
+%D We need this one soon:
+
+\normalprotected\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
+
+%D Some expected plain variants follow. We don't reuse registers because we
+%D don't want clashes.
+
+\let \p@ \onepoint
+\let \m@ne \minusone
+\let \z@ \zeropoint
+\let \@ne \plusone
+\let \tw@ \plustwo
+\let \thr@@ \plusthree
+\let \sixt@@n \plussixteen
+\let \@cclv \pluscclv
+\let \@cclvi \pluscclvi
+\let \voidb@x \voidbox
+\newtoks \toks@ % \scratchtoks
+
+%D We define \type {\newif} a la plain \TEX, but will redefine it later. As
+%D Knuth says:
+%D
+%D \startnarrower
+%D And here's a different sort of allocation: for example,
+%D
+%D \starttyping
+%D \newif\iffoo
+%D \stoptyping
+%D
+%D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}.
+%D \stopnarrower
+
+% \normalprotected\def\newif#1%
+% {\count@\escapechar
+% \escapechar\minusone
+% \expandafter\expandafter\expandafter\def\new_if #1{true}{\let#1\iftrue }%
+% \expandafter\expandafter\expandafter\def\new_if#1{false}{\let#1\iffalse}%
+% \new_if#1{false}% the condition starts out false
+% \escapechar\count@}
+%
+% \def\new_if#1#2%
+% {\csname\expandafter\if@\string#1#2\endcsname}
+%
+% \bgroup % `if' is required
+% \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}
+% \egroup
+
+% We use \csstring so there is no need to push/pop escapechar.
+% We use different names so that we get a better error message.
+%
+% \normalprotected\def\newif#1%
+% {\let\new_if_saved\newif
+% \let\newif\new_if_check
+% \expandafter\expandafter\expandafter\def\new_if_cs #1{true}{\let#1\iftrue }%
+% \expandafter\expandafter\expandafter\def\new_if_cs#1{false}{\let#1\iffalse}%
+% \new_if_cs#1{false}%
+% \let\newif\new_if_saved}
+%
+% \normalprotected\def\new_if_cs#1#2%
+% {\csname\expandafter\newif\csstring#1#2\endcsname}
+%
+% We wrap all into one macro:
+
+\normalprotected\def\newif#1%
+ {\let\new_if_saved\newif
+ \let\newif\new_if_check
+ \expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
+ \expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
+ \csname\expandafter\newif\csstring#1false\endcsname
+ \let\newif\new_if_saved}
+
+\bgroup
+ \normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}}
+\egroup
+
+%D Let's test this one:
+
+\newif\ifdone
+\newif\iffound
+
+\let\htdp\boxtotal
+
+%D A few shortcuts:
+
+\normalprotected\def\udef {\normalprotected\def }
+\normalprotected\def\ugdef{\normalprotected\gdef}
+\normalprotected\def\uedef{\normalprotected\edef}
+\normalprotected\def\uxdef{\normalprotected\xdef}
+
+%D For a while we keep the following, as systems like tikz need it. Best
+%D not use that one \CONTEXT.
+
+\let\active\activecatcode
+
+%D Constants to be used with \type {\currentgrouptype}.
+
+\chardef\bottomlevelgroupcode = 0
+\chardef\simplegroupcode = 1
+\chardef\hboxgroupcode = 2
+\chardef\adjustedhboxgroupcode = 3
+\chardef\vboxgroupcode = 4
+\chardef\vtopgroupcode = 5
+\chardef\aligngroupcode = 6
+\chardef\noaligngroupcode = 7
+\chardef\outputgroupcode = 8
+\chardef\mathgroupcode = 9
+\chardef\discretionarygroupcode = 10
+\chardef\insertgroupcode = 11
+\chardef\vcentergroupcode = 12
+\chardef\mathchoicegroupcode = 13
+\chardef\semisimplegroupcode = 14
+\chardef\mathshiftgroupcode = 15
+\chardef\mathleftgroupcode = 16
+\chardef\vadjustgroupcode = \insertgroupcode
+
+%D Constants to be used with \type {\interactionmode}.
+
+\chardef\batchmodecode \zerocount
+\chardef\nonstopmodecode \plusone
+\chardef\scrollmodecode \plustwo
+\chardef\errorstopmodecode \plusthree
+
+%D Constants to be used with \type {\lastnodetype}. The \type {\lastnodetype}
+%D primitive is \ETEX\ compliant. The valid range is still -1 .. 15 and glyph nodes
+%D have number 0 (used to be char node) and ligature nodes are mapped to 7. That way
+%D macro packages can use the same symbolic names as in traditional \ETEX. Keep in
+%D mind that the internal node numbers are different and that there are more node
+%D types that 15. The mode parameter forces \LUAMETATEX\ to use the real node
+%D numbers.
+
+\internalcodesmode\plusone
+
+%D Constants to be used with \type {\currentiftype}. I wonder if we will ever
+%D use these in \CONTEXT. We have a few more anyway and in \LUAMETATEX\ we
+%D have different numbers. So for now let's just not define them. The
+%D previously mentioned mode parameters enables the real numbers (we have
+%D some more and they are therefore ordered differently).
+
+% \chardef\charifcode = 1
+% \chardef\catifcode = 2
+% \chardef\numifcode = 3
+% \chardef\dimifcode = 4
+% \chardef\oddifcode = 5
+% \chardef\vmodeifcode = 6
+% \chardef\hmodeifcode = 7
+% \chardef\mmodeifcode = 8
+% \chardef\innerifcode = 9
+% \chardef\voidifcode = 10
+% \chardef\hboxifcode = 11
+% \chardef\vboxifcode = 12
+% \chardef\xifcode = 13
+% \chardef\eofifcode = 14
+% \chardef\trueifcode = 15
+% \chardef\falseifcode = 16
+% \chardef\caseifcode = 17
+% \chardef\definedifcode = 18
+% \chardef\csnameifcode = 19
+% \chardef\fontcharifcode = 20
+
+%D Of course we want even bigger log files, so we copied this from the \ETEX\
+%D source files.
+%D
+%D When watching such logs, beware of nasty side effects of \type {\scantokens},
+%D as in:
+%D
+%D \starttyping
+%D \bgroup
+%D \lccode`a=12\lowercase{\xdef\whatever{a}}\egroup
+%D \def\whatever{test \whatever test}
+%D \scantokens\expandafter{\whatever}
+%D \egroup
+%D \stoptyping
+%D
+%D In \LUATEX\ we have ways around this.
+
+% no longer \errorstopmode cf. plain tex 3.141592653
+
+\normalprotected\def\tracingall
+ {\tracingonline \plusone
+ \tracingcommands \plusthree
+ \tracingstats \plustwo
+ \tracingpages \plusone
+ \tracingoutput \plusone
+ \tracinglostchars \plustwo
+ \tracingmacros \plustwo
+ \tracingparagraphs\plusone
+ \tracingrestores \plusone
+ \showboxbreadth \maxdimen
+ \showboxdepth \maxdimen
+ \tracinggroups \plusone
+ \tracingifs \plusone
+ \tracingscantokens\plusone
+ \tracingnesting \plusone
+ \tracingassigns \plustwo}
+
+\normalprotected\def\loggingall
+ {\tracingall
+ \tracingonline \zerocount}
+
+\normalprotected\def\tracingnone
+ {\tracingassigns \zerocount
+ \tracingnesting \zerocount
+ \tracingscantokens\zerocount
+ \tracingifs \zerocount
+ \tracinggroups \zerocount
+ \showboxdepth \plusthree
+ \showboxbreadth \plusfive
+ \tracingrestores \zerocount
+ \tracingparagraphs\zerocount
+ \tracingmacros \zerocount
+ \tracinglostchars \plusone
+ \tracingoutput \zerocount
+ \tracingpages \zerocount
+ \tracingstats \zerocount
+ \tracingcommands \zerocount
+ \tracingonline \zerocount}
+
+%D When we want to see a box we can as well show all of it.
+
+\showboxdepth \maxdimen
+\showboxbreadth\maxdimen
+
+%D Just for tracing purposes we set:
+
+\tracingstats\plusone
+
+%D Here we also save \type {\input}, more will be saved later.
+
+\ifdefined\normalinput \else \let\normalinput\input \fi
+
+%D We don't like outer commands, and we always want access to the original
+%D \type {\input} primitive.
+
+\let\normalouter\outer \def\outer{} % no longer \relax
+
+%D To circumvent dependencies, we can postpone certain initializations to
+%D dumping time, by appending them to the \type {\everydump} token register.
+
+\ifdefined\normaldump \else \let\normaldump\dump \fi
+
+\newtoks\everydump
+
+\def\dump{\the\everydump\normaldump}
+
+%D The same applies for the startup actions.
+
+\ifdefined\normaleveryjob \else \let\normaleveryjob\everyjob \fi
+
+\let\everyjob\relax \newtoks\everyjob
+
+\normaleveryjob{\the\everyjob}
+
+%D \macros
+%D {newconditional,
+%D settrue, setfalse,
+%D ifconditional,then}
+%D
+%D \TEX's lacks boolean variables, although the \PLAIN\ format implements \type
+%D {\newif}. The main disadvantage of this scheme is that it takes three hash table
+%D entries. A more memory saving alternative is presented here. A conditional is
+%D defined by:
+%D
+%D \starttyping
+%D \newconditional\doublesided
+%D \setfalse
+%D \stoptyping
+%D Setting a conditional is done by \type{\settrue} and
+%D \type{\setfalse}:
+%D
+%D \starttyping
+%D \settrue\doublesided
+%D \setfalse
+%D \stoptyping
+%D while testing is accomplished by:
+%D
+%D \starttyping
+%D \ifconditional\doublesided ... \else ... \fi
+%D \setfalse
+%D \stoptyping
+%D We cannot use the simple scheme:
+%D
+%D \starttyping
+%D \def\settrue #1{\let#1=\iftrue}
+%D \def\setfalse#1{\let#1=\iffalse}
+%D \stoptyping
+%D
+%D Such an implementation gives problems with nested conditionals. The next
+%D implementation is about as fast and just as straightforward:
+
+\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef
+\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef
+
+\normalprotected\def\settrue #1{\let#1\conditionaltrue }
+\normalprotected\def\setfalse#1{\let#1\conditionalfalse}
+
+\normalprotected\def\settruevalue #1{\expandafter\let\csname#1\endcsname\conditionaltrue }
+\normalprotected\def\setfalsevalue#1{\expandafter\let\csname#1\endcsname\conditionalfalse}
+
+\let\newconditional\setfalse
+\let\ifconditional \ifcase
+
+\let\then\relax % so that we can say: \ifnum1>2\then -)
+
+% This one has to be unprotected otherwise we get a files-ends-to-soon but it's ok
+% as conditions expand anyway.
+
+\def\quitcondition{\orelse\iffalse}
+
+%D \macros
+%D {newmacro,setnewmacro,newfraction}
+%D
+%D Let's be complete and also introduce some definers. These are not mandate
+%D but handy for grepping.
+
+\normalprotected\def\newmacro #1{\let#1\empty}
+\normalprotected\def\setnewmacro#1{\let#1}
+
+\def\!!zerocount{0}
+\def\!!plusone {1}
+
+\normalprotected\def\newfraction#1{\let#1\!!plusone}
+
+%D It would be handy to have a primitive \type {\unless\ifcase} because then we
+%D could use nicer values. Anyhow, this conditional code used to be in the \type
+%D {syst-aux} module but is now promoted to here.
+
+%D \macros
+%D {ifzeropt}
+%D
+%D The next macro is both cosmetic and byte saving. It is pretty \type
+%D {\if}||safe too. It can be used in cases like:
+%D
+%D \starttyping
+%D \ifzeropt \somedimen ... \else ... \fi
+%D \stoptyping
+
+\let\ifzeropt\ifcase
+
+% these token list helpers might move to syst-aux.mkiv
+%
+% we assume a \cs. not toks0 or so
+%
+% \normalprotected\def\appendtotoks #1#{\def\temp{#1}\afterassignment\doappendtotoks \scratchtoks=}
+% \normalprotected\def\prependtotoks#1#{\def\temp{#1}\afterassignment\doprependtotoks\scratchtoks=}
+
+\newtoks\t_syst_toks_temp \let\m_syst_toks_temp\t_syst_toks_temp
+
+\normalprotected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=}
+\normalprotected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=}
+
+% \def\syst_toks_append {\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\m_syst_toks_temp\the\t_syst_toks_temp}}}
+% \def\syst_toks_prepend{\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\t_syst_toks_temp\the\m_syst_toks_temp}}}
+
+\normalprotected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=}
+\normalprotected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=}
+
+\def\syst_toks_append_l {\normalexpanded{\m_syst_toks_temp{\the\m_syst_toks_temp\the\t_syst_toks_temp}}}
+\def\syst_toks_prepend_l{\normalexpanded{\m_syst_toks_temp{\the\t_syst_toks_temp\the\m_syst_toks_temp}}}
+
+\def\syst_toks_append_g {\global\syst_toks_append_l }
+\def\syst_toks_prepend_g{\global\syst_toks_prepend_l}
+
+\normalprotected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next}
+\normalprotected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next}
+
+\def\syst_toks_add_l{\m_syst_toks_temp\expandafter\bgroup\the\m_syst_toks_temp}
+\def\syst_toks_add_g{\global\syst_toks_add_l}
+
+\normalprotected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes
+\normalprotected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes
+
+%D \macros
+%D {begcsname}
+%D
+%D Handy for \ETEX-only usage (avoids making \type {\relax}'s:
+
+% \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi}
+
+\let\begcsname\begincsname
+
+%D Now come a few macros that might be needed in successive loading. We redefine the
+%D \type {\par} primitive pretty soon so that we get the equivalents right.
+
+% too tricky: \par is use more often than a par starts so we have too much change
+% that we get assymetrical behaviour
+%
+% \newtoks\everyendpar
+%
+% \normalprotected\def\endpar{\the\everyendpar\normalpar}
+% \normalprotected\def\par {\endpar}
+%
+% \normalprotected\def\reseteverypar
+% {\everypar \emptytoks
+% \everyendpar\emptytoks}
+
+\normalprotected\def\reseteverypar
+ {\everypar\emptytoks}
+
+\let\endgraf\par
+\let\endline\cr
+
+\normalprotected\def\null{\hpack{}}
+
+%D The following two might be overloaded later on but some modules need then
+%D earlier. These functionality is reflected in the name and will not change.
+
+% \bgroup
+% \catcode`\^^M=\activecatcode%
+% \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}%
+% \glet^^M\par%
+% \egroup
+%
+% \bgroup
+% \gdef\obeyspaces{\catcode`\ \activecatcode}%
+% \obeyspaces\glet =\space%
+% \egroup
+
+\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par}
+\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space}
+
+% %D A constant:
+%
+% \let\endoflinetoken=^^M
+
+%D Also needed might be a simple loop structure and we borrow plain \TEX's one
+%D as it is often expected to be present and it is about the fastest you can
+%D get. Beware: this macro does not support nested loops. We use a namespace
+%D prefix \type {@@pln}.
+
+\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go
+
+%D The following makes \type {\loop} \unknown\ \type {\if} \unknown\ \type
+%D {\repeat} skippable (clever trick):
+
+\let\repeat\fi % so both \loop and \repeat are reserved words!
+
+%D The original (no \type {@@pln} there):
+%D
+%D \starttyping
+%D \def\@@plniterate{\@@plnbody\let\next\@@plniterate\else\let\next\relax\fi\next}
+%D \stoptyping
+%D
+%D A more efficient alternative:
+%D
+%D \starttyping
+%D \def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\expandafter\relax\fi}
+%D \stoptyping
+%D
+%D An even more efficient one:
+
+\def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\fi}
+
+%D We don't define a real output routine yet but at least get rid of pages:
+
+\output{\shipout\box\normalpagebox}
+
+%D Although we don't add pagenumbers yet we alias the default register used
+%D for counting pages:
+
+\countdef\pageno\zerocount \pageno\plusone % first page is number 1
+
+%D Beside the raw counter \type {\pageno} the \type {\folio} macro provides
+%D the value.
+
+\def\folio{\the\pageno} % kind of expected and therefore reserved
+
+%D The following registers are kind of standard and (for the moment) we define
+%D them here. This might change.
+
+\newskip \bigskipamount \bigskipamount = 12pt plus 4pt minus 4pt
+\newskip \medskipamount \medskipamount = 6pt plus 2pt minus 2pt
+\newskip \smallskipamount \smallskipamount = 3pt plus 1pt minus 1pt
+
+\baselineskip = 12pt
+\lineskip = 1pt
+\lineskiplimit = 0pt
+
+%D Sometimes kerns make more sense than glue but we need to be in the
+%D right mode:
+
+\normalprotected\def\vkern{\ifhmode\par \fi\kern}
+\normalprotected\def\hkern{\ifvmode\dontleavehmode\fi\kern}
+
+%D Again a few kind-of-extensions the core. These come from plain \TEX\ but
+%D are probably not used in \CONTEXT.
+
+\newskip \hideskip \hideskip = -1000pt plus 1fill
+\newskip \centering \centering = 0pt plus 1000pt minus 1000pt
+
+\def\hidewidth % for alignment entries that can stick out
+ {\hskip\hideskip}
+
+\def\ialign % initialized \halign
+ {\everycr\emptytoks
+ \tabskip\zeroskip
+ \halign}
+
+\newcount \mscount
+
+\def\spanomit{\span\omit} % bypass error message
+
+\def\multispan#1%
+ {\omit
+ \mscount#1\relax
+ \loop
+ \ifnum\mscount>\plusone
+ \spanomit \advance\mscount\minusone
+ \repeat}
+
+\let\nopdfcompression \relax
+\let\onlypdfobjectcompression\relax
+\let\maximumpdfcompression \relax
+\let\normalpdfcompression \relax
+
+%D Basic status stuff.
+
+\newif\ifproductionrun
+
+%D For those who expect this \unknown
+
+\ifx\fmtname \undefined \def\fmtname {ConTeXt Initial TeX} \fi
+\ifx\fmtversion\undefined \def\fmtversion{3.1415926} \fi
+
+%D A few bonus macros:
+
+\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
+\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax}
+
+%D These could be set at the \LUA\ end instead:
+
+\edef\texenginename {\directlua{tex.print(LUATEXENGINE)}}
+\edef\texengineversion {\directlua{tex.print(LUATEXVERSION)}}
+\edef\texenginefunctionality{\directlua{tex.print(LUATEXFUNCTIONALITY)}}
+
+%D We have no reason not to enable this:
+
+\savingvdiscards\plusone
+
+%D We only can set this one via directives (system.synctex) and we only support
+%D the context variant. This will go away completely.
+
+\newcount\synctex \let\normalsynctex\synctex
+
+%D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero.
+
+\voffset\zeropoint \let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset
+\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset
+
+\matheqnogapstep\zerocount % for now
+
+%D Now we define a few helpers that we need in a very early stage. We have no
+%D message system yet but redundant definitions are fatal anyway.
+
+\newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes
+
+\def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>}
+%def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet
+
+\normalprotected\def\installsystemnamespace#1%
+ {\ifcsname ??#1\endcsname
+ \immediate\write\statuswrite{fatal error: duplicate system namespace '#1'}%
+ \expandafter\normalend
+ \else
+ \global\advance\c_syst_helpers_n_of_namespaces\plusone
+ \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}%
+ \fi}
+
+%D It makes more sense to have these here:
+
+\let\normalsuperscript \Usuperscript
+\let\normalsubscript \Usubscript
+\let\normalnosuperscript\Unosuperscript
+\let\normalnosubscript \Unosubscript
+\let\normalstartimath \Ustartmath
+\let\normalstopimath \Ustopmath
+\let\normalstartdmath \Ustartdisplaymath
+\let\normalstopdmath \Ustopdisplaymath
+
+%D Also better here:
+
+\def\wildcardsymbol{*}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-ntb.mkiv b/tex/context/base/mkiv/tabl-ntb.mkiv
index 1cf5ad3dc..879cd33e3 100644
--- a/tex/context/base/mkiv/tabl-ntb.mkiv
+++ b/tex/context/base/mkiv/tabl-ntb.mkiv
@@ -11,13 +11,12 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This module has a more modern variant in xtables but as we follow a bit
-%D different approach with settings there, this mechanism will stay. In fact
-%D each of them has its advantages. This module could be sped up a bit and made
-%D more efficient by delegating some housekeeping to \LUA\ but it's not worth
-%D the effort. The code could me made more readable but again, there is no
-%D real purpose in it. If needed I can squeeze out a few more percentages
-%D runtime.
+%D This module has a more modern variant in xtables but as we follow a bit different
+%D approach with settings there, this mechanism will stay. In fact each of them has
+%D its advantages. This module could be sped up a bit and made more efficient by
+%D delegating some housekeeping to \LUA\ but it's not worth the effort. The code
+%D could me made more readable but again, there is no real purpose in it. If needed
+%D I can squeeze out a few more percentages runtime.
% columndistance 'optimized' ... needs checking
%
@@ -27,8 +26,8 @@
% sometimes this helps (with nc going wild): \setupTABLE[maxwidth=100cm]
%
-% bug: width 3cm is not honored and column becomes too wide
-% as given width is added to distributed width
+% bug: width 3cm is not honored and column becomes too wide as given width is added
+% to distributed width
%
% \bTABLE
% \bTR
@@ -61,16 +60,14 @@
% \stopcelltable
% \stoptext
-%D As always, this is the n\high{th} version. Much time went in
-%D trying to speed up the many cell calculations, some
-%D optimizations were rejected in order not to complicate this
-%D module too much (and in order to prevail extensibility). In the
+%D As always, this is the n\high{th} version. Much time went in trying to speed up
+%D the many cell calculations, some optimizations were rejected in order not to
+%D complicate this module too much (and in order to prevail extensibility). In the
%D meantime we've sacrified some speed for readability.
\unprotect
-%D The next alternative also takes care of preceding and following
-%D white space.
+%D The next alternative also takes care of preceding and following white space.
%D
%D \startbuffer
%D \bTABLE[left={(},right={)},top=\startnarrower,bottom=\stopnarrower]
@@ -203,8 +200,8 @@
\newbox\b_tabl_ntb_final
-%D We have already prepared the previous macros for nesting,
-%D so we only have to pop in the right ones:
+%D We have already prepared the previous macros for nesting, so we only have to pop
+%D in the right ones:
\newcount\c_tabl_level
@@ -861,8 +858,8 @@
\def\tabl_ntb_tn[#1]#2\eTN
{\tabl_ntb_td[#1]\digits#2\relax\eTD}
-%D Vit Zyka needed the option to create a distance between columns, so I
-%D added support for individual column distances.
+%D Vit Zyka needed the option to create a distance between columns, so I added
+%D support for individual column distances.
%D
%D \startbuffer
%D % \setupTABLE[c][each][distance=2em]
@@ -884,9 +881,8 @@
%D
%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
%D
-%D and he provided patches for the global left and right margin distances
-%D as well as the columndistance (although i changed the names -). Here
-%D is his testcase:
+%D and he provided patches for the global left and right margin distances as well as
+%D the columndistance (although i changed the names -). Here is his testcase:
%D
%D \startbuffer
%D \framed[offset=overlay]\bgroup
@@ -1233,8 +1229,8 @@
\def\tabl_ntb_prelocate_okay
{\expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks}
-% We use aligments to handle the empty (skipped) columns, so
-% that we don't have to (re|)|calculate these.
+%D We use aligments to handle the empty (skipped) columns, so that we don't have to
+%D (re|)|calculate these.
\let\m_tabl_ntb_saved_row\!!zerocount
\let\m_tabl_ntb_saved_col\!!zerocount
@@ -1734,6 +1730,8 @@
\fi}%
\ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths E#1\fi}
+% todo: use scratchcounters, not !! ones
+
\def\tabl_ntb_check_heights_one_indeed
{\!!countb\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax
% check row span
@@ -1815,19 +1813,6 @@
{\writestatus\m!TABLE{\space\space\recurselevel: \the\dimexpr\tabl_ntb_get_wid\recurselevel}}%
\endgroup}
-% \def\tabl_ntb_char_align
-% {\doifelse{\naturaltablelocalparameter\c!aligncharacter}\v!yes
-% \tabl_ntb_char_align_indeed\gobbletwoarguments}
-
-% \def\tabl_ntb_char_align_indeed#1#2#3% row column data
-% {\edef\alignmentclass{#2}%
-% \edef\alignmentcharacter{\naturaltablelocalparameter\c!alignmentcharacter}%
-% \ifcase\c_tabl_tbl_pass\or
-% \setfirstpasscharacteralign\checkalignment{#3}% {\strut#2\unskip}%
-% \fi % force hsize, so always a second
-% \setsecondpasscharacteralign \checkalignment{#3}% {\strut#2\unskip}%
-% \ignorespaces}
-
\def\tabl_ntb_char_align % called often
{\edef\p_characteralign{\naturaltablelocalparameter\c!aligncharacter}%
\ifx\p_characteralign\v!yes
@@ -1857,25 +1842,12 @@
\unexpanded\def\tabl_ntb_cell_process_x#1#2[#3]#4%
{}
-% problem: when span doesn't break we can have a span that is the sum of
-% cells but still to small .. chicken egg problem ... for that we should
-% also have a smallest width run
+% problem: when span doesn't break we can have a span that is the sum of cells but
+% still to small .. chicken egg problem ... for that we should also have a smallest
+% width run
%
% nilling the background makes a run upto 25% faster
-% \def\tabl_ntb_cell_process_a_check_span_one
-% {\ifautosqueezeTBLspan
-% \edef\p_width{\naturaltablelocalparameter\c!width}%
-% \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
-% \else
-% \donetrue
-% \fi
-% \ifdone % brr, 0
-% \ifnum\scratchcounter>\plusone
-% \tabl_ntb_set_spn\c_tabl_ntb_col
-% \fi
-% \fi}
-
\def\tabl_ntb_cell_process_a_check_span_one
{\ifautosqueezeTBLspan
\edef\p_width{\naturaltablelocalparameter\c!width}%
@@ -1889,47 +1861,6 @@
\fi
\fi}
-% \def\tabl_ntb_cell_process_a_check_span_two_yes
-% {\iftightTBLcolspan
-% \donefalse
-% \else
-% \ifnum\scratchcounter>\plusone
-% \begingroup
-% \edef\p_width{\naturaltablelocalparameter\c!width}%
-% \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
-% \ifdone
-% \endgroup
-% \edef\p_option{\naturaltablelocalparameter\c!option}%
-% \ifx\p_option\v!tight\donefalse\else\donetrue\fi
-% \else
-% % a dimension
-% \endgroup
-% \donefalse
-% \fi
-% \else
-% \edef\p_option{\naturaltablelocalparameter\c!option}%
-% \ifx\p_option\v!tight\donefalse\else\donetrue\fi
-% \fi
-% \fi
-% \ifdone
-% \ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
-% \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
-% \fi
-% \fi}
-
-% \def\tabl_ntb_cell_process_a_check_span_two_nop
-% {\ifnum\scratchcounter>\plusone
-% \edef\p_width{\naturaltablelocalparameter\c!width}%
-% \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
-% \else
-% \donetrue
-% \fi
-% \ifdone
-% \ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
-% \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
-% \fi
-% \fi}
-
\let\tabl_ntb_cell_process_a_check_span_two_yes\relax
\def\tabl_ntb_cell_process_a_check_span_two_nop
@@ -1953,9 +1884,9 @@
\anch_backgrounds_text_level_start
\inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}%
\anch_backgrounds_text_level_stop
-\ifcase\c_anch_backgrounds_text_count\else
- \tabl_ntb_let_bck{#1}{#2}\c_anch_backgrounds_text_state
-\fi
+ \ifcase\c_anch_backgrounds_text_count\else
+ \tabl_ntb_let_bck{#1}{#2}\c_anch_backgrounds_text_state
+ \fi
}%
\scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
\ifdim\wd\scratchbox>\scratchdimen
@@ -2059,12 +1990,12 @@
\else
\setnaturaltablelocalparameter\c!height{\d_tabl_ntb_height}%
\fi
-\ifcase\c_anch_backgrounds_text_count\else
- \edef\p_region{\naturaltablelocalparameter\c!region}%
- \ifx\p_region\empty\ifnum\tabl_ntb_get_bck{#1}{#2}>\zerocount
- \letnaturaltablelocalparameter\c!region\v!yes
- \fi\fi
-\fi
+ \ifcase\c_anch_backgrounds_text_count\else
+ \edef\p_region{\naturaltablelocalparameter\c!region}%
+ \ifx\p_region\empty\ifnum\tabl_ntb_get_bck{#1}{#2}>\zerocount
+ \letnaturaltablelocalparameter\c!region\v!yes
+ \fi\fi
+ \fi
\inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}}%
\hskip\tabl_ntb_get_dis{#2}}
@@ -2198,12 +2129,6 @@
\let\eTDs\relax
\let\eTRs\relax
-% \unexpanded\def\bTDs[#1]#2\eTDs
-% {\normalexpanded{\bTD[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTD}
-%
-% \unexpanded\def\bTRs[#1]#2\eTRs
-% {\normalexpanded{\bTR[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTR}
-
\unexpanded\def\bTDs[#1]#2\eTDs
{\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD}
diff --git a/tex/context/base/mkiv/tabl-ntb.mkxl b/tex/context/base/mkiv/tabl-ntb.mkxl
new file mode 100644
index 000000000..e80ff06d6
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-ntb.mkxl
@@ -0,0 +1,2138 @@
+%D \module
+%D [ file=tabl-ntb,
+%D version=2000.04.18,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Natural Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module has a more modern variant in xtables but as we follow a bit different
+%D approach with settings there, this mechanism will stay. In fact each of them has
+%D its advantages. This module could be sped up a bit and made more efficient by
+%D delegating some housekeeping to \LUA\ but it's not worth the effort. The code
+%D could me made more readable but again, there is no real purpose in it. If needed
+%D I can squeeze out a few more percentages runtime.
+
+% columndistance 'optimized' ... needs checking
+%
+% we don't need the alignment mechanism .. we can just pack the row in a box
+
+\writestatus{loading}{ConTeXt Table Macros / Natural Tables}
+
+% sometimes this helps (with nc going wild): \setupTABLE[maxwidth=100cm]
+%
+% bug: width 3cm is not honored and column becomes too wide as given width is added
+% to distributed width
+%
+% \bTABLE
+% \bTR
+% \bTD test \eTD
+% \bTD \framed[height=3cm]{test} \eTD
+% \bTD[width=3cm] \dorecurse{30}{a } \eTD
+% \bTD \input ward \eTD
+% \eTR
+% \bTR
+% \bTD test \eTD
+% \bTD \framed[height=3cm]{test} \eTD
+% \bTD \dorecurse{30}{a } \eTD
+% \bTD \input ward \eTD
+% \eTR
+% \eTABLE
+
+% \unexpanded\def\startrow {\bTR}
+% \unexpanded\def\stoprow {\eTR}
+% \unexpanded\def\startcell#1\stopcell{\bTD#1\eTD}
+% \let\stopcell \relax
+% \let\startcelltable \bTABLE
+% \let\stopcelltable \eTABLE
+
+% \starttext
+% \startcelltable
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \stopcelltable
+% \stoptext
+
+%D As always, this is the n\high{th} version. Much time went in trying to speed up
+%D the many cell calculations, some optimizations were rejected in order not to
+%D complicate this module too much (and in order to prevail extensibility). In the
+%D meantime we've sacrified some speed for readability.
+
+\unprotect
+
+%D The next alternative also takes care of preceding and following white space.
+%D
+%D \startbuffer
+%D \bTABLE[left={(},right={)},top=\startnarrower,bottom=\stopnarrower]
+%D \bTR \bTD something \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\ifdefined\dotagTABLEcell \else \let\dotagTABLEcell \relax \fi % todo: namespace
+\ifdefined\dotagTABLEsignal \else \let\dotagTABLEsignal\relax \fi % todo: namespace
+
+\let\tabl_ntb_next_level\relax
+
+\newtoks\t_tabl_ntb_cell_start
+\newtoks\t_tabl_ntb_cell_stop
+
+\appendtoks
+ \naturaltablelocalparameter\c!left
+ \delayedbegstrut
+\to \t_tabl_ntb_cell_start
+
+\appendtoks
+ \delayedendstrut
+ \naturaltablelocalparameter\c!right
+\to \t_tabl_ntb_cell_stop
+
+\appendtoks
+ \flushpostponednodedata
+ % maybe: \the\neverypar
+\to \t_tabl_ntb_cell_start
+
+\unexpanded\def\tabl_ntb_cell_start
+ {% \inhibitblank
+ \dotagTABLEcell
+ %\tabl_ntb_next_level
+ \font_styles_math_reset
+ \usenaturaltablelocalstyleandcolor\c!style\c!color
+ \everypar\t_tabl_ntb_cell_start
+ \font_styles_math_start}
+
+\unexpanded\def\tabl_ntb_cell_stop
+ {\font_styles_math_stop
+ \ifhmode
+ \the\t_tabl_ntb_cell_stop
+ \par % added 13/4/2006
+ \orelse\ifdim\prevdepth<\zeropoint % =-1000pt ?
+ % not sure yet:\naturaltablelocalparameter\c!right
+ \vskip-\strutdp
+ \else
+ \removebottomthings
+ \fi}
+
+% maybe:
+%
+% \unexpanded\def\tabl_ntb_cell_stop
+% {\ifhmode
+% \the\t_tabl_ntb_cell_stop
+% \par % added 13/4/2006
+% \else
+% % not sure yet:\naturaltablelocalparameter\c!right
+% \par
+% \ifhmode
+% % \removeunwantedspaces
+% \else\ifdim\prevdepth<\zeropoint % =-1000pt ?
+% \vskip-\strutdp
+% \else
+% \removebottomthings
+% \fi\fi
+% \fi}
+
+\newcount\c_tabl_ntb_row
+\newcount\c_tabl_ntb_col
+\newcount\c_tabl_ntb_spn
+
+\newcount\c_tabl_ntb_nx
+\newcount\c_tabl_ntb_ny
+
+\setnewconstant\c_tabl_ntb_cell \plusone
+\setnewconstant\c_tabl_ntb_none \plustwo
+
+\newcount\c_tabl_ntb_current_row
+\newcount\c_tabl_ntb_current_col
+\newcount\c_tabl_ntb_current_row_one
+\newcount\c_tabl_ntb_current_col_one
+\newcount\c_tabl_ntb_current_row_two
+\newcount\c_tabl_ntb_current_col_two
+\newcount\c_tabl_ntb_current_row_three
+\newcount\c_tabl_ntb_current_col_three
+\newcount\c_tabl_ntb_current_row_four
+\newcount\c_tabl_ntb_current_col_four
+
+\newcount\c_tabl_ntb_running_col
+\newcount\c_tabl_ntb_maximum_row
+\newcount\c_tabl_ntb_maximum_col
+\newcount\c_tabl_ntb_maximum_row_span
+\newcount\c_tabl_ntb_maximum_col_span
+
+\newcount\c_tabl_ntb_encountered_col
+\newcount\c_tabl_ntb_encountered_max
+
+\newtoks\t_tabl_ntb
+\newtoks\t_tabl_ntb_row
+
+\newconstant\c_tabl_tbl_pass
+
+\newtoks\t_tabl_ntb_head
+\newtoks\t_tabl_ntb_next
+\newtoks\t_tabl_ntb_body
+\newtoks\t_tabl_ntb_foot
+
+\newcount\c_tabl_ntb_n_of_head_lines
+\newcount\c_tabl_ntb_n_of_next_lines
+\newcount\c_tabl_ntb_n_of_hdnx_lines
+
+\newdimen\d_tabl_ntb_height
+\newdimen\d_tabl_ntb_width
+
+\newdimen\d_tabl_ntb_leftmargindistance
+\newdimen\d_tabl_ntb_rightmargindistance
+\newdimen\d_tabl_ntb_columndistance
+\newdimen\d_tabl_ntb_maxwidth
+
+\newtoks\everyTABLEpass % public
+
+\newcount\tablecellrows % public (needs checking)
+\newcount\tablecellcolumns % public (needs checking)
+
+\newbox\b_tabl_ntb_final
+
+%D We have already prepared the previous macros for nesting, so we only have to pop
+%D in the right ones:
+
+\newcount\c_tabl_level
+
+\installglobalmacrostack\m_tabl_ntb_saved_row
+\installglobalmacrostack\m_tabl_ntb_saved_col
+
+\unexpanded\def\tabl_ntb_table_push
+ {\ifnum\m_tabl_tbl_level>\plusone
+ \tabl_ntb_parameters_reset
+ % we need a proper count push/pop
+ \xdef\m_tabl_ntb_saved_row{\the\c_tabl_ntb_row}\push_macro_m_tabl_ntb_saved_row
+ \xdef\m_tabl_ntb_saved_col{\the\c_tabl_ntb_col}\push_macro_m_tabl_ntb_saved_col
+ \else
+ \global\intabletrue
+ \fi}
+
+\unexpanded\def\tabl_ntb_table_pop
+ {\ifnum\m_tabl_tbl_level>\plusone
+ \pop_macro_m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row
+ \pop_macro_m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col
+ \else
+ \global\intablefalse
+ \fi}
+
+\unexpanded\def\tabl_ntb_next_level
+ {\advance\c_tabl_level\plusone
+ \edef\m_tabl_tbl_level{\the\c_tabl_level}}
+
+\unexpanded\def\tabl_ntb_prev_level
+ {\advance\c_tabl_level\minusone
+ \edef\m_tabl_tbl_level{\the\c_tabl_level}}
+
+\tabl_ntb_next_level % go to level 1
+
+\installcorenamespace{naturaltable} % was tbl
+\installcorenamespace{naturaltablelocal} % was tbltbl
+
+\installdirectcommandhandler \??naturaltable {naturaltable} % \??naturaltable
+\installsimpleframedcommandhandler \??naturaltablelocal {naturaltablelocal} \??naturaltablelocal
+
+\installcorenamespace{naturaltabletal}
+\installcorenamespace{naturaltablegal}
+\installcorenamespace{naturaltablenob}
+\installcorenamespace{naturaltabletag}
+\installcorenamespace{naturaltablecol}
+\installcorenamespace{naturaltablerow}
+\installcorenamespace{naturaltablewd}
+\installcorenamespace{naturaltableht}
+\installcorenamespace{naturaltabledp}
+\installcorenamespace{naturaltablewid}
+\installcorenamespace{naturaltablehei}
+\installcorenamespace{naturaltabledis}
+\installcorenamespace{naturaltableaut}
+\installcorenamespace{naturaltablebck}
+%installcorenamespace{naturaltablefwd} % forcedwidth
+\installcorenamespace{naturaltabletxt}
+\installcorenamespace{naturaltablespn}
+\installcorenamespace{naturaltableref}
+\installcorenamespace{naturaltableset}
+\installcorenamespace{naturaltablecell}
+\installcorenamespace{naturaltablesqueeze}
+\installcorenamespace{naturaltabletok}
+
+\letvalue{\??naturaltablesqueeze }\donefalse
+\letvalue{\??naturaltablesqueeze\v!fit }\donetrue
+\letvalue{\??naturaltablesqueeze\v!fixed}\donetrue
+\letvalue{\??naturaltablesqueeze\v!broad}\donetrue
+\letvalue{\??naturaltablesqueeze\v!local}\donetrue
+
+\def\tabl_ntb_let_gal{\expandafter\glet\csname\??naturaltablegal\m_tabl_tbl_level\endcsname}
+\def\tabl_ntb_get_gal{\csname\??naturaltablegal\m_tabl_tbl_level\endcsname}
+
+\def\tabl_ntb_let_tal#1{\expandafter\glet\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname}
+\def\tabl_ntb_get_tal#1{\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname}
+
+\def\tabl_ntb_set_nob#1{\expandafter\let\csname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone}
+\def\tabl_ntb_get_nob#1{\ifcsname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone\else\zerocount\fi}
+
+%def\tabl_ntb_set_tag#1#2{\expandafter\edef\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_col#1#2{\expandafter\edef\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_row#1#2{\expandafter\edef\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_let_tag#1#2{\expandafter\let\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_let_col#1#2{\expandafter\let\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_let_row#1#2{\expandafter\let\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+%def\tabl_ntb_set_wd#1#2{\expandafter\xdef\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+\def\tabl_ntb_set_ht#1#2{\expandafter\xdef\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+
+%def\tabl_ntb_let_wd#1#2{\expandafter\glet\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+\def\tabl_ntb_let_ht#1#2{\expandafter\glet\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+
+\def\tabl_ntb_get_tag#1#2{\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_col#1#2{\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_row#1#2{\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+%def\tabl_ntb_get_wd#1#2{\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_ht#1#2{\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_set_wid#1{\expandafter\xdef\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_hei#1{\expandafter\xdef\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_dis#1{\expandafter\xdef\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_aut#1{\expandafter\xdef\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+
+\def\tabl_ntb_let_wid#1{\expandafter\glet\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_hei#1{\expandafter\glet\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_dis#1{\expandafter\glet\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_aut#1{\expandafter\glet\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+
+\def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_aut#1{\csname \??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname}
+
+\def\tabl_ntb_let_bck#1#2{\global\expandafter\chardef\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_get_bck#1#2{\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_tag_pattern#1#2{\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2}
+\def\tabl_ntb_row_pattern#1#2{\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2}
+\def\tabl_ntb_col_pattern#1#2{\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2}
+
+\def\tabl_ntb_tag_doif #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_tag_doifnot #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
+\def\tabl_ntb_tag_doifelse#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\def\tabl_ntb_row_doif #1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_col_doif #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_col_doifnot #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
+
+%D If we ever run into memory issues we can do:
+%
+% \def\tabl_ntb_let_tag#1#2#3%
+% {\ifx#3\c_tabl_ntb_none\else
+% \expandafter\let\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname#3%
+% \fi}
+%
+% \def\tabl_ntb_get_tag#1#2%
+% {\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname
+% \lastnamedcs
+% \else
+% \c_tabl_ntb_none
+% \fi}
+
+% not used
+%
+% \def\tabl_ntb_tag_state#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+% \def\tabl_ntb_row_state#1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+% \def\tabl_ntb_col_state#1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+
+%def\tabl_ntb_set_spn #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone}
+%def\tabl_ntb_spn_doifelse#1{\doifelse {\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname}\!!plusone}
+
+%def\tabl_ntb_set_spn #1{\setvalue {\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
+%def\tabl_ntb_spn_doifelse#1{\doifelsevalue{\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
+
+\def\tabl_ntb_let_ref #1#2{\expandafter\glet\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_ref #1#2{\expandafter\xdef\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+%def\tabl_ntb_get_ref #1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi}
+\def\tabl_ntb_get_ref #1#2{\begincsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_set_spn #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone}
+\def\tabl_ntb_spn_doifelse#1{\ifcase0\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname\relax % could be inlined
+ \expandafter\secondoftwoarguments % unset
+ \else
+ \expandafter\firstoftwoarguments % a span
+ \fi}
+
+% keep for a while:
+%
+% \unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% nasty: we restore the level
+% {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\expandafter\endcsname\expandafter
+% {\expandafter\def\expandafter\m_tabl_tbl_level\expandafter{\m_tabl_tbl_level}\tabl_ntb_cell_process{#3}{#4}[#5]{#6}}}
+
+\unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6%
+ {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname
+ {\tabl_ntb_cell_process{#3}{#4}[#5]{\tabl_ntb_next_level#6\tabl_ntb_prev_level}}}
+
+\def\tabl_ntb_get_txt#1#2%
+ {\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+% to be changed:
+
+\newif\ifsqueezeTBLspan \squeezeTBLspantrue % spans one column cell over multi column par cells
+\newif\ifautosqueezeTBLspan \autosqueezeTBLspantrue % unless explicit widths are given
+\newif\ifautoTBLspread \autoTBLspreadfalse
+\newif\ifautoTBLhsize \autoTBLhsizetrue
+\newif\ifautoTBLrowspan \autoTBLrowspantrue
+\newif\ifautoTBLemptycell \autoTBLemptycelltrue
+\newif\ifautoTBLcheckwidth \autoTBLcheckwidthtrue
+\newif\ifappendTBLsetups \appendTBLsetupstrue
+\newif\ifenableTBLbreak \enableTBLbreakfalse
+\newif\ifmultipleTBLheads \multipleTBLheadsfalse
+\newif\iftightTBLrowspan \tightTBLrowspantrue
+\newif\iftightTBLcolspan \tightTBLcolspanfalse
+
+\newconditional \c_tabl_ntb_trace_widths
+
+\installtextracker
+ {tables.natural.widths}
+ {\settrue \c_tabl_ntb_trace_widths}
+ {\setfalse\c_tabl_ntb_trace_widths}
+
+% so far
+
+\unexpanded\def\tabl_ntb_cell_process#1#2[#3]{}
+
+\unexpanded\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax
+\unexpanded\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax
+\unexpanded\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax
+
+\unexpanded\def\setupTABLE
+ {\dotripleempty\tabl_ntb_setup}
+
+\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
+
+\def\tabl_ntb_setup
+ {\ifthirdargument
+ \expandafter\tabl_ntb_setup_three
+ \orelse\ifsecondargument
+ \doubleexpandafter\tabl_ntb_setup_two
+ \else
+ \doubleexpandafter\tabl_ntb_setup_one
+ \fi}
+
+\def\tabl_ntb_setup_one[#1][#2][#3]%
+ {\setupcurrentnaturaltablelocal[#1]}
+
+\def\tabl_ntb_setup_xy[#1][#2][#3]%
+ {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[#1##1][#3]}%
+ \processcommalist[#2]\tabl_ntb_setup_step}
+
+\def\tabl_ntb_setup_un[#1][#2][#3]%
+ {\def\tabl_ntb_setup_step##1%
+ {\def\tabl_ntb_setup_step_step####1{\tabl_ntb_parameters_set[\c!x##1\c!y####1][#3]}%
+ \processcommalist[#2]\tabl_ntb_setup_step_step}%
+ \processcommalist[#1]\tabl_ntb_setup_step}
+
+\def\tabl_ntb_setup_each[#1][#2][#3]% ignores #3
+ {\tabl_ntb_parameters_set[#1\v!each][#2]}
+
+\def\tabl_ntb_setup_ux[#1][#2][#3]% ignores #3
+ {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[\c!x##1][#2]}%
+ \processcommalist[#1]\tabl_ntb_setup_step}
+
+\installcorenamespace{naturaltablesetupthree}
+\installcorenamespace{naturaltablesetuptwo}
+
+%def\tabl_ntb_setup_three[#1]{\csname\??naturaltablesetupthree\ifcsname\??naturaltablesetupthree#1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+%def\tabl_ntb_setup_two [#1]{\csname\??naturaltablesetuptwo \ifcsname\??naturaltablesetuptwo #1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+
+\def\tabl_ntb_setup_three[#1]{\ifcsname\??naturaltablesetupthree#1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_un\fi[#1]}
+\def\tabl_ntb_setup_two [#1]{\ifcsname\??naturaltablesetuptwo #1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_ux\fi[#1]}
+
+\setvalue{\??naturaltablesetupthree \v!row}[#1]{\tabl_ntb_setup_xy [\c!y]}
+\setvalue{\??naturaltablesetupthree \v!column}[#1]{\tabl_ntb_setup_xy [\c!x]}
+\setvalue{\??naturaltablesetupthree \v!start}[#1]{\tabl_ntb_setup_xy [\v!start]}
+\setvalue{\??naturaltablesetupthree \v!header}[#1]{\tabl_ntb_setup_xy [\v!header]}
+
+\setvalue{\??naturaltablesetuptwo \v!row}[#1]{\tabl_ntb_setup_each[\c!y]}
+\setvalue{\??naturaltablesetuptwo \v!column}[#1]{\tabl_ntb_setup_each[\c!x]}
+\setvalue{\??naturaltablesetuptwo \v!start}[#1]{\tabl_ntb_setup_each[\v!start]}
+\setvalue{\??naturaltablesetuptwo \v!header}[#1]{\tabl_ntb_setup_each[\v!header]}
+
+\letvalue{\??naturaltablesetupthree\s!unknown}\tabl_ntb_setup_un
+\letvalue{\??naturaltablesetuptwo \s!unknown}\tabl_ntb_setup_ux
+
+\letcsnamecsname\csname\??naturaltablesetupthree r\endcsname\csname\??naturaltablesetupthree \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree c\endcsname\csname\??naturaltablesetupthree\v!column\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree y\endcsname\csname\??naturaltablesetupthree \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree x\endcsname\csname\??naturaltablesetupthree\v!column\endcsname
+
+\letcsnamecsname\csname\??naturaltablesetuptwo r\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo c\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo y\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo x\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname
+
+\def\tabl_ntb_parameters_set[#1][#2]%
+ {\ifappendTBLsetups
+ \ifcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
+ \def\tabl_ntb_parameters_get[##1]%
+ {\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[##1,#2]}}%
+ \csname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
+ \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
+ \else
+ \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
+ \fi
+ \else
+ \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
+ \fi}
+
+% % \setupTABLE [y] [first][background=color,backgroundcolor=blue,frame=off,bottomframe=on,topframe=on,framecolor=white]
+% \setupTABLE [first][first][backgroundcorner=2,corner=10,frame=on]
+% \setupTABLE [last] [first][backgroundcorner=4,corner=12,frame=on]
+%
+% \setupTABLE [row] [each] [background=color,backgroundcolor=blue,frame=on,framecolor=white]
+% \setupTABLE [first][2] [corner=8]
+% \setupTABLE [last] [2] [corner=5]
+% \setupTABLE [first][last] [corner=7]
+% \setupTABLE [last] [last] [corner=6]
+%
+% \startTEXpage
+% \bTABLE[frame=off,align=middle]
+% \bTR \bTD one \eTD \bTD two \eTD \bTD three \eTD \eTR
+% \bTR \bTD first \eTD \bTD second \eTD \bTD third \eTD \eTR
+% \bTR \bTD alpha \eTD \bTD beta \eTD \bTD gamma \eTD \eTR
+% \eTABLE
+% \stopTEXpage
+%
+% \setupTABLE [first] [two][corner=2] % special case
+% \setupTABLE [last] [two][corner=4] % special case
+%
+% % % \setupTABLE [one] [first] ... special case of span
+%
+% \startTEXpage
+% \bTABLE[frame=off,align=middle]
+% \bTR \bTD one \eTD \bTD two \eTD \bTD three \eTD \eTR
+% \bTR \bTD first \eTD \bTD second \eTD \bTD third \eTD \eTR
+% \eTABLE
+% \stopTEXpage
+
+%D By default rowspans are tight but you can change that:
+%D
+%D \startbuffer
+%D \bTABLE
+%D \bTR[height=20pt] \bTH 1. col \eTH \bTH 2. col \eTH \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \bTD[nr=2] 2 rows in 2. col \eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 1. col\eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=3] 3 rows in 2. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \eTABLE
+%D
+%D \bTABLE
+%D \bTR[height=20pt] \bTH 2. col \eTH \bTH 1. col \eTH \eTR
+%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 2. col \eTD \bTD 1 row in 1. col \eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 1. col\eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=3] 3 rows in 2. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D With \type {\tightTBLrowspanfalse} we get:
+%D
+%D \start \tightTBLrowspanfalse \getbuffer \stop
+
+\let\tabl_ntb_setup_section\relax
+
+\unexpanded\def\tabl_ntb_setup_cell#1#2% cell over col over row
+ {\tabl_ntb_setup_section % already forgotten
+ \edef\m_tabl_ntb_positive_row{\number#1}%
+ \edef\m_tabl_ntb_positive_col{\number#2}%
+ \edef\m_tabl_ntb_negative_row{\the\numexpr-\c_tabl_ntb_maximum_row+#1+\minusone\relax}%
+ \edef\m_tabl_ntb_negative_col{\the\numexpr-\c_tabl_ntb_maximum_col+#2+\minusone\relax}%
+ % saves tokens (no speed gain)
+ \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_tbl_level:}%
+ % each each
+ \begincsname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!y\v!each\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!each\endcsname
+ % odd even
+ \begincsname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+ % row/col number combinations
+ \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname
+ \naturaltablelocalparameter\c!extras
+ \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname
+ \naturaltablelocalparameter\c!extras
+ \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
+ % first/last combinations
+ \ifnum\m_tabl_ntb_positive_row=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!y\v!first\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+ \begincsname\m_tabl_ntb_prefix\c!y\v!last\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname
+ \fi\fi
+ % special case: two rows and last row : two&first and two&last (round corners)
+ \ifnum\c_tabl_ntb_maximum_row=\plustwo\relax
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname
+ \fi\fi
+ \fi
+ \ifnum\tabl_ntb_get_col\m_tabl_ntb_positive_row\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax % top span over whole width
+ \ifnum\m_tabl_ntb_positive_row=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname
+ \fi
+ \fi
+ % header things
+ \ifnum#1>\c_tabl_ntb_n_of_hdnx_lines\else
+ \begincsname\m_tabl_ntb_prefix\v!header\v!each\endcsname
+ \begincsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname
+ \fi
+ % explicit cells
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname
+ % local
+ \begincsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname
+ % done
+ \relax}
+
+% we cannot use +n (checking on number/last/first would slow down too much)
+%
+% \setupTABLE[r] [2][color=red]
+% \setupTABLE[r] [-2][color=red]
+% \setupTABLE[c] [2][color=green]
+% \setupTABLE[c] [-2][color=green]
+% \setupTABLE[4] [4][color=blue]
+% \setupTABLE[-4][-4][color=blue]
+%
+% \bTABLE
+% \dorecurse{10}{\bTR \dorecurse{6}{\bTD xxx \eTD} \eTR}
+% \eTABLE
+
+\let\m_tabl_ntb_before_split\empty
+\let\m_tabl_ntb_after_split \empty
+\let\m_tabl_ntb_same_page \empty
+
+% split + page:
+%
+% \bTABLE[split=yes]
+% \bTR \bTD left \eTD\bTD right \eTD\eTR
+% \bTR[after=\page] \bTD left \eTD\bTD right \eTD\eTR
+% \bTR \bTD left \eTD\bTD right \eTD\eTR
+% \eTABLE
+
+\unexpanded\def\tabl_ntb_tr
+ {\c_tabl_ntb_running_col\zerocount
+ \c_tabl_ntb_encountered_col\zerocount
+ \advance\c_tabl_ntb_maximum_row\plusone
+ \iffirstargument
+ \expandafter\tabl_ntb_tr_yes
+ \else
+ \expandafter\gobbleoneoptional
+ \fi}
+
+\def\tabl_ntb_tr_yes[#1]%
+ {\setvalue{\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_maximum_row}{\setupcurrentnaturaltablelocal[#1]}}
+
+\def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr}
+\def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc}
+
+\unexpanded\def\tabl_ntb_td
+ {\advance\c_tabl_ntb_encountered_col\plusone
+ \iffirstargument
+ \expandafter\tabl_ntb_td_yes
+ \else
+ \expandafter\tabl_ntb_td_nop
+ \fi}
+
+\def\tabl_ntb_td_yes[#1]#2\eTD
+ {\letnaturaltableparameter\c!ny \m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx \m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc \plusone
+ \letnaturaltableparameter\c!nr \plusone
+ \letnaturaltableparameter\c!n \c_tabl_ntb_running_col
+ \letnaturaltableparameter\c!m \empty
+ \letnaturaltableparameter\c!action\empty % not that important
+ \setupcurrentnaturaltable[#1]%
+ %
+ \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax
+ \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax
+ % goto first cell n/m=cellnumber
+ \edef\m_tabl_ntb_n{\naturaltableparameter\c!n}%
+ \edef\m_tabl_ntb_m{\naturaltableparameter\c!m}%
+ %
+ \ifx\m_tabl_ntb_n\empty
+ \global\advance\c_tabl_ntb_spn\c_tabl_ntb_nx\relax
+ \orelse\ifnum\m_tabl_ntb_n=\c_tabl_ntb_running_col\else
+ \tabl_ntb_td_pass_n{#1}%
+ \fi
+ \ifx\m_tabl_ntb_m\empty \else
+ \ifnum\m_tabl_ntb_m=\c_tabl_ntb_running_col\else
+ \tabl_ntb_td_pass_m{#1}%
+ \fi
+ \fi
+ \doloop % skip over columns that result from earlier span
+ {\advance\c_tabl_ntb_running_col\plusone
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
+ \exitloop
+ \fi}%
+ % fill r*c cells and set span
+ \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax
+ \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax
+ \ifnum\c_tabl_ntb_nx=\plusone
+ \ifnum\c_tabl_ntb_ny=\plusone
+ \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
+ \fi
+ \else
+ \tabl_ntb_cell_preset
+ \fi
+ \else
+ \tabl_ntb_cell_preset
+ \fi
+ % set values
+ \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}%
+ \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}%
+ % the action key will change!
+ \tabl_ntb_set_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\naturaltableparameter\c!action}%
+ % save text
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
+ {#1}{#2}%
+ \ifnum\c_tabl_ntb_encountered_col>\c_tabl_ntb_encountered_max
+ \c_tabl_ntb_encountered_max\c_tabl_ntb_encountered_col
+ \fi}
+
+\def\tabl_ntb_td_nop[#1]#2\eTD
+ {\global\advance\c_tabl_ntb_spn\plusone\relax
+ \doloop
+ {\advance\c_tabl_ntb_running_col\plusone
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
+ \exitloop
+ \fi}%
+ \c_tabl_ntb_nx\plusone
+ \c_tabl_ntb_ny\plusone
+ \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
+ \fi
+ \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}%
+ \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}%
+ \tabl_ntb_let_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\empty
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
+ {#1}{#2}%
+ \ifnum\c_tabl_ntb_encountered_col>\c_tabl_ntb_encountered_max
+ \c_tabl_ntb_encountered_max\c_tabl_ntb_encountered_col
+ \fi}
+
+\def\tabl_ntb_td_pass_n#1%
+ {\scratchcounter\numexpr\m_tabl_ntb_n-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax
+ \ifnum\scratchcounter>\zerocount
+ \normalexpanded{\tabl_ntb_td[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no]}\eTD
+ \fi
+ \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc\plusone
+ \letnaturaltableparameter\c!nr\plusone
+ \setupcurrentnaturaltable[#1]%
+ \letnaturaltableparameter\c!n \empty
+ \letnaturaltableparameter\c!m \empty}
+
+\def\tabl_ntb_td_pass_m#1%
+ {\scratchcounter\numexpr\m_tabl_ntb_m-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax
+ \dorecurse\scratchcounter{\normalexpanded{\tabl_ntb_td[\c!n=,\c!m=]}\eTD}%
+ % can be sped up
+ \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc\plusone
+ \letnaturaltableparameter\c!nr\plusone
+ \setupcurrentnaturaltable[#1]%
+ \letnaturaltableparameter\c!n \empty
+ \letnaturaltableparameter\c!m \empty}
+
+\def\tabl_ntb_cell_preset
+ {\c_tabl_ntb_current_row\c_tabl_ntb_maximum_row
+ \c_tabl_ntb_current_col\c_tabl_ntb_running_col
+ \dorecurse\c_tabl_ntb_ny\tabl_ntb_cell_preset_rows
+ % check max column
+ \advance\c_tabl_ntb_current_col\minusone
+ \ifnum\c_tabl_ntb_current_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_current_col
+ \fi}
+
+\def\tabl_ntb_cell_preset_rows
+ {\c_tabl_ntb_current_col\c_tabl_ntb_running_col
+ \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_nx}%
+ \ifnum\c_tabl_ntb_nx>\c_tabl_ntb_maximum_row_span\relax
+ \c_tabl_ntb_maximum_row_span\c_tabl_ntb_nx
+ \fi
+ \dorecurse\c_tabl_ntb_nx\tabl_ntb_cell_preset_cells
+ \advance\c_tabl_ntb_current_row\plusone}
+
+\def\tabl_ntb_cell_preset_cells
+ {\tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
+ \advance\c_tabl_ntb_current_col\plusone}
+
+%D The usage of n and m:
+%D
+%D \startbuffer
+%D \bTABLE[width=3em]
+%D \bTR\bTD d1 \eTD\bTD[n=2] d2 \eTD\bTD[n=5] d5 \eTD\bTD[n=7] d7 \eTD\eTR
+%D \bTR\bTD f1 \eTD\bTD[n=4] f4 \eTD\bTD[n=5] f5 \eTD\bTD[n=7] f7 \eTD\eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \bTABLE[width=3em]
+%D \bTR\bTD d1 \eTD\bTD[m=2] d2 \eTD\bTD[m=5] d5 \eTD\bTD[m=7] d7 \eTD\eTR
+%D \bTR\bTD f1 \eTD\bTD[m=4] f4 \eTD\bTD[m=5] f5 \eTD\bTD[m=7] f7 \eTD\eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \bTABLE[frame=on]
+%D \bTR \bTH[nc=3] One \eTH \bTH[m=4] Four \eTH\eTR
+%D \bTR \bTD a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
+%D \eTABLE
+%D
+%D \bTABLE[frame=on]
+%D \bTR \bTH[nr=2] One \eTH \bTH[m=3] Three \eTH\eTR
+%D \bTR \bTD[m=3] a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
+%D \bTR \bTD[m=3] a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\tabl_ntb_th[#1]#2\eTH
+ {\tabl_ntb_td[#1,\c!color=\naturaltablelocalparameter\c!headcolor,\c!style=\naturaltablelocalparameter\c!headstyle,\c!aligncharacter=\v!no]#2\eTD}
+
+\def\tabl_ntb_tn[#1]#2\eTN
+ {\tabl_ntb_td[#1]\digits#2\relax\eTD}
+
+%D Vit Zyka needed the option to create a distance between columns, so I added
+%D support for individual column distances.
+%D
+%D \startbuffer
+%D % \setupTABLE[c][each][distance=2em]
+%D \setupTABLE[c][1][distance=2em]
+%D \setupTABLE[c][2][distance=3em]
+%D
+%D \bTABLE
+%D \bTR \bTD test \eTD \bTD test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD[nx=2] test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD test \eTD \bTD[nx=2] test \eTD \eTR
+%D \eTABLE
+%D
+%D \bTABLE[option=stretch]
+%D \bTR \bTD test \eTD \bTD test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD[nx=2] test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD test \eTD \bTD[nx=2] test \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+%D
+%D and he provided patches for the global left and right margin distances as well as
+%D the columndistance (although i changed the names -). Here is his testcase:
+%D
+%D \startbuffer
+%D \framed[offset=overlay]\bgroup
+%D \setupTABLE[column][2][align=left]%
+%D \setupTABLE[column][3][align=right]%
+%D \bTABLE[columndistance=2cm,leftmargindistance=.3cm,rightmargindistance=.5cm]
+%D \bTR \bTH[nc=3] Table head\eTH \eTR
+%D \bTR \bTD[nc=2] AB\eTD \bTD C\eTD \eTR
+%D \bTR \bTD[nc=2,align=left] AB\eTD \bTD C\eTD \eTR
+%D \bTR \bTD[nc=2,align=middle] AB\eTD \bTD C\eTD \eTR
+%D \bTR \bTD A\eTD \bTD B\eTD \bTD C\eTD \eTR
+%D \bTR \bTD Aa\eTD \bTD Bb\eTD \bTD Cccc\eTD \eTR
+%D \bTR \bTD[nc=3,align=middle] ABC\eTD \eTR
+%D \eTABLE
+%D \egroup
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+
+% to be done: head <raw> foot, dus state var
+
+\unexpanded\def\bTABLEhead{\dosingleempty\tabl_ntb_head} \let\eTABLEhead\relax
+\unexpanded\def\bTABLEnext{\dosingleempty\tabl_ntb_next} \let\eTABLEnext\relax
+\unexpanded\def\bTABLEbody{\dosingleempty\tabl_ntb_body} \let\eTABLEbody\relax
+\unexpanded\def\bTABLEfoot{\dosingleempty\tabl_ntb_foot} \let\eTABLEfoot\relax
+
+\def\tabl_ntb_head[#1]#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head}
+\def\tabl_ntb_next[#1]#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next}
+\def\tabl_ntb_body[#1]#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body}
+\def\tabl_ntb_foot[#1]#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot}
+
+\def\tabl_ntb_section[#1]#2% also used in tabl-nte
+ {\unexpanded\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}%
+ #2%
+ \let\tabl_ntb_setup_section\relax}
+
+\def\tabl_ntb_preset_parameters% each odd|even level / can be sped up but only once per table
+ {\begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
+ \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname
+ \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname}
+
+\unexpanded\def\bTABLE
+ {\dosingleempty\tabl_ntb_table}
+
+\def\tabl_ntb_table[#1]%
+ {\tabl_ntb_table_push
+ % box not here
+ \bgroup
+ \pushpostponednodedata
+ \t_tabl_ntb_head\emptytoks
+ \t_tabl_ntb_next\emptytoks
+ \t_tabl_ntb_body\emptytoks
+ \t_tabl_ntb_foot\emptytoks
+ \ifhmode\kern\zeropoint\fi % blocks \removeunwantedspaces: check this on icare handelingsschema
+ \resetcharacteralign % new
+ \setupcurrentnaturaltablelocal[\c!align={\v!right,\v!broad,\v!high},#1]%
+ %
+ \d_tabl_ntb_leftmargindistance \naturaltablelocalparameter\c!leftmargindistance\relax
+ \d_tabl_ntb_rightmargindistance\naturaltablelocalparameter\c!rightmargindistance\relax
+ \d_tabl_ntb_columndistance \naturaltablelocalparameter\c!columndistance\relax
+ \d_tabl_ntb_maxwidth \naturaltablelocalparameter\c!maxwidth\relax
+ %
+ \usesetupsparameter\naturaltablelocalparameter
+ \doifelse{\naturaltablelocalparameter\c!textwidth}\v!local
+ {\hsize\availablehsize}
+ {\hsize\naturaltablelocalparameter\c!textwidth}%
+ \enableTBLbreakfalse
+ \multipleTBLheadsfalse
+ \autoTBLspreadfalse
+ \tightTBLcolspanfalse
+ \processaction
+ [\naturaltablelocalparameter\c!split]
+ [ \v!yes=>\enableTBLbreaktrue,
+ \v!repeat=>\enableTBLbreaktrue\multipleTBLheadstrue,
+ \v!auto=>\ifinsidesplitfloat\enableTBLbreaktrue\fi]
+ \processaction
+ [\naturaltablelocalparameter\c!header]
+ [\v!repeat=>\multipleTBLheadstrue]%
+ \tabl_ntb_preset_parameters
+ \processallactionsinset
+ [\naturaltablelocalparameter\c!option]
+ [\v!stretch=>\autoTBLspreadtrue,%
+ \v!tight=>\tightTBLcolspantrue]%
+ \linewidth\naturaltablelocalparameter\c!rulethickness % needs to be frozen
+ \dontcomplain
+ \c_tabl_ntb_running_col \zerocount
+ \c_tabl_ntb_maximum_col \zerocount
+ \c_tabl_ntb_maximum_row \zerocount
+ \c_tabl_ntb_maximum_row_span\plusone
+ \let\currentTABLErow \tabl_ntb_current_row
+ \let\currentTABLEcolumn\tabl_ntb_current_column
+ \let\nofTABLErows \tabl_ntb_n_of_rows
+ \let\nofTABLEcolumns \tabl_ntb_n_of_columns
+ \let\bTR\dobTR
+ \let\bTD\dobTD
+ \let\bTH\dobTH
+ \let\bTN\dobTN}
+
+\def\tabl_ntb_current_row {\m_tabl_ntb_positive_row}
+\def\tabl_ntb_current_column{\m_tabl_ntb_positive_col}
+\def\tabl_ntb_n_of_rows {\number\c_tabl_ntb_maximum_row}
+\def\tabl_ntb_n_of_columns {\number\c_tabl_ntb_maximum_col}
+
+\let\currentTABLErow \!!zerocount
+\let\currentTABLEcolumn\!!zerocount
+\let\nofTABLErows \!!zerocount
+\let\nofTABLEcolumns \!!zerocount
+
+% there is no gain in a \doifelsenextoptionalcs variant
+
+\unexpanded\def\dobTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte
+\unexpanded\def\dobTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte
+\unexpanded\def\dobTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte
+\unexpanded\def\dobTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte
+
+% permits \expanded{\bTD ... \eTD}
+
+\let\bTR\relax \unexpanded\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows
+\let\bTD\relax \unexpanded\def\eTD{\ignorespaces}
+\let\bTH\relax \unexpanded\def\eTH{\ignorespaces}
+\let\bTN\relax \unexpanded\def\eTN{\ignorespaces}
+
+\unexpanded\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode
+ {% tricky and dirty order -)
+ \doifelsesometoks\t_tabl_ntb_head % slow, better a flag
+ {\the\t_tabl_ntb_head
+ \c_tabl_ntb_n_of_head_lines\c_tabl_ntb_maximum_row\relax
+ \doifelsesometoks\t_tabl_ntb_next
+ {\the\t_tabl_ntb_next
+ \c_tabl_ntb_n_of_next_lines\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_n_of_head_lines\relax}%
+ {\c_tabl_ntb_n_of_next_lines\zerocount}% was 1
+ \c_tabl_ntb_n_of_hdnx_lines\c_tabl_ntb_maximum_row}
+ {\c_tabl_ntb_n_of_head_lines\zerocount % was 1
+ \c_tabl_ntb_n_of_next_lines\zerocount
+ \c_tabl_ntb_n_of_hdnx_lines\zerocount}%
+ \the\t_tabl_ntb_body
+ \the\t_tabl_ntb_foot
+ \removeunwantedspaces % only if hmode
+ % finish cells
+ \tabl_ntb_loop_one
+ % to be sure
+ \tabl_ntb_loop_two
+ % check and do
+ \ifcase\c_tabl_ntb_maximum_col\else
+ \startTBLprocessing
+ \tabl_ntb_table_start
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_row_start
+ \c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \normalexpanded{\tabl_ntb_cell{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}}%
+ \tabl_ntb_row_stop}%
+ \removeunwantedspaces % only if hmode
+ \tabl_ntb_table_stop
+ \stopTBLprocessing
+ % wrong ! ! ! better to have an auto-offset-overlay
+ % \ifnum\m_tabl_tbl_level>1
+ % \vskip-\strutdp
+ % \fi
+ \fi
+ % tracing
+ % \iftrue
+ % \blank \tttf
+ % \dorecurse\c_tabl_ntb_maximum_row
+ % {\c_tabl_ntb_current_row\recurselevel\relax
+ % \dorecurse\c_tabl_ntb_maximum_col
+ % {\c_tabl_ntb_current_col\recurselevel\relax
+ % [r=\the\c_tabl_ntb_current_row,c=\the\c_tabl_ntb_current_col,h=\the\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col,w=\the\dimexpr\tabl_ntb_get_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col]}%
+ % \par}%
+ % \blank
+ % \fi
+ \poppostponednodedata
+ \egroup
+ \tabl_ntb_table_pop}
+
+\def\tabl_ntb_loop_one
+ {\dorecurse\c_tabl_ntb_maximum_row{\tabl_ntb_loop_one_rows}}
+
+\def\tabl_ntb_loop_one_rows
+ {\c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_one_cells}
+
+\def\tabl_ntb_loop_one_cells
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_loop_one_cells_indeed
+ \fi}
+
+\def\tabl_ntb_loop_one_cells_indeed
+ {\c_tabl_ntb_current_col_two\c_tabl_ntb_current_col
+ \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row
+ \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
+ \doloop
+ {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
+ \doloop
+ {\ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
+ \exitloop
+ \else
+ \advance\c_tabl_ntb_current_col_one\plusone
+ \ifnum\c_tabl_ntb_current_col_one>\c_tabl_ntb_maximum_col\relax
+ \exitloop
+ \fi
+ \fi}%
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
+ \exitloop
+ \else
+ \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row_one
+ \c_tabl_ntb_current_col_two\c_tabl_ntb_current_col_one
+ \advance\c_tabl_ntb_current_row_one\plusone
+ \ifnum\c_tabl_ntb_current_row_one>\c_tabl_ntb_maximum_row
+ \exitloop
+ \fi
+ \fi}%
+ \ifnum\c_tabl_ntb_current_row_two>\c_tabl_ntb_maximum_row\c_tabl_ntb_current_row_two\c_tabl_ntb_maximum_row\fi
+ \ifnum\c_tabl_ntb_current_col_two>\c_tabl_ntb_maximum_col\c_tabl_ntb_current_col_two\c_tabl_ntb_maximum_col\fi
+ \c_tabl_ntb_current_row_two\numexpr\c_tabl_ntb_current_row_two-\c_tabl_ntb_current_row+\plusone\relax
+ \c_tabl_ntb_current_col_two\numexpr\c_tabl_ntb_current_col_two-\c_tabl_ntb_current_col+\plusone\relax
+ \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
+ \dorecurse\c_tabl_ntb_current_row_two
+ {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
+ \tabl_ntb_set_col\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one{\the\c_tabl_ntb_current_col_two}%
+ \dorecurse\c_tabl_ntb_current_col_two
+ {\tabl_ntb_let_tag\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\c_tabl_ntb_none
+ \advance\c_tabl_ntb_current_col_one\plusone}%
+ \advance\c_tabl_ntb_current_row_one\plusone}%
+ \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_col_two}%
+ \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row_two}%
+ \ifautoTBLemptycell
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}%
+ {\c!option=\v!tight}{\strut\kern\scaledpoint}% the kern forces the tight
+ \fi}
+
+\def\tabl_ntb_loop_two
+ {\dorecurse\c_tabl_ntb_maximum_row\tabl_ntb_loop_two_rows}
+
+\def\tabl_ntb_loop_two_rows
+ {\c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_two_cells}
+
+\def\tabl_ntb_loop_two_cells
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname
+ \scratchcounter\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_current_row+\plusone\relax
+ \ifnum\tabl_ntb_get_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col>\scratchcounter
+ \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\scratchcounter}%
+ \fi
+ \fi
+ \tabl_ntb_let_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
+ %tabl_ntb_let_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
+ \ifcsname\tabl_ntb_col_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_let_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zerocount
+ \fi
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
+ \fi}
+
+\let\startTBLprocessing\relax % public
+\let\stopTBLprocessing \relax % public
+
+\newcount\c_tabl_prelocated_rows % \prelocateTBLrows{1000} may speed up large tables
+
+% \def\tabl_ntb_row_start{\t_tabl_ntb_row\emptytoks}
+% \def\tabl_ntb_row_stop {\normalexpanded{\t_tabl_ntb{\the\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\the\t_tabl_ntb_row\tabl_ntb_row_align_stop}}}
+
+\def\tabl_ntb_row_start
+ {\t_tabl_ntb_row\emptytoks}
+
+\def\tabl_ntb_row_stop
+ {\ifenableTBLbreak
+ \tabl_ntb_row_stop_split
+ \else
+ \tabl_ntb_row_stop_boxed
+ \fi}
+
+\def\tabl_ntb_row_stop_boxed
+ {% \noindent % no, else double leftskip in narrower
+ \etoksapp\t_tabl_ntb
+ {% no need for init
+ \tabl_ntb_row_align_start
+ \the\t_tabl_ntb_row
+ \tabl_ntb_row_align_stop}}
+
+\def\tabl_ntb_row_stop_split
+ {\ifcsname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname
+ \tabl_ntb_row_stop_split_yes
+ \else
+ \tabl_ntb_row_stop_split_nop
+ \fi}
+
+\def\tabl_ntb_row_stop_split_nop
+ {\etoksapp\t_tabl_ntb
+ {\tabl_ntb_row_align_reset
+ \tabl_ntb_row_align_start
+ \the\t_tabl_ntb_row
+ \tabl_ntb_row_align_stop}}
+
+\def\tabl_ntb_row_stop_split_yes
+ {\begingroup
+ \csname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname
+ \xdef\m_tabl_ntb_before_split{\naturaltablelocalparameter\c!before}% to be checked
+ \xdef\m_tabl_ntb_after_split {\naturaltablelocalparameter\c!after}% to be checked
+ \xdef\m_tabl_ntb_same_page {\naturaltablelocalparameter\c!samepage}%
+ \endgroup
+ \etoksapp\t_tabl_ntb
+ {\tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}%
+ \tabl_ntb_row_align_start
+ \the\t_tabl_ntb_row
+ \tabl_ntb_row_align_stop}}
+
+\unexpanded\def\tabl_ntb_row_align_set#1#2#3%
+ {\xdef\m_tabl_ntb_before_split{#1}%
+ \xdef\m_tabl_ntb_after_split {#2}%
+ \xdef\m_tabl_ntb_same_page {#3}}
+
+\unexpanded\def\tabl_ntb_row_align_reset
+ {\glet\m_tabl_ntb_before_split\empty
+ \glet\m_tabl_ntb_after_split \empty
+ \glet\m_tabl_ntb_same_page \empty}
+
+\def\tabl_ntb_prelocate_error
+ {\writestatus\m!TABLE{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}}
+
+% \prelocateTBLrows{1000} % may speed up large tables
+
+\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway
+ {\dostepwiserecurse\c_tabl_prelocated_rows{#1}\plusone
+ {\expandafter\newtoks\csname\??naturaltabletok\recurselevel\endcsname}%
+ \def\tabl_ntb_row_start
+ {\ifnum\c_tabl_ntb_row<\c_tabl_prelocated_rows\relax
+ \tabl_ntb_prelocate_okay
+ \else
+ \tabl_ntb_prelocate_error
+ \fi}%
+ \def\tabl_ntb_row_stop
+ {\etoksapp\t_tabl_ntb
+ {\tabl_ntb_row_align_start
+ \the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname
+ \tabl_ntb_row_align_stop}}%
+ \global\c_tabl_prelocated_rows#1\relax}
+
+\def\tabl_ntb_prelocate_okay
+ {\expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks}
+
+%D We use aligments to handle the empty (skipped) columns, so that we don't have to
+%D (re|)|calculate these.
+
+\let\m_tabl_ntb_saved_row\!!zerocount
+\let\m_tabl_ntb_saved_col\!!zerocount
+
+\unexpanded\def\tabl_ntb_row_align_start
+ {\global\advance\c_tabl_ntb_row\plusone
+ \global\c_tabl_ntb_col\plusone
+ \global\c_tabl_ntb_spn\zerocount
+ \tabl_ntb_row_align_start_inject
+ \dostarttagged\t!tablerow\empty
+ \hbox\bgroup
+ \kern\dimexpr\d_tabl_ntb_leftmargindistance\relax}
+
+\unexpanded\def\tabl_ntb_row_align_stop
+ {\kern\dimexpr\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance\relax
+ \egroup
+ \dostoptagged
+ \tabl_ntb_row_align_stop_inject}
+
+\unexpanded\def\tabl_ntb_before_page
+ {\ifx\m_tabl_ntb_same_page\v!before
+ % \blank[\v!samepage,\v!strong]%
+ \unpenalty
+ \nobreak
+ \orelse\ifx\m_tabl_ntb_same_page\v!both
+ % \blank[\v!samepage,\v!strong]%
+ \unpenalty
+ \nobreak
+ \fi}
+
+\unexpanded\def\tabl_ntb_after_page
+ {\ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines
+ \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount
+ \unpenalty
+ \ifx\m_tabl_ntb_same_page\v!after
+ % \blank[\v!samepage,\v!strong]%
+ \nobreak
+ \orelse\ifx\m_tabl_ntb_same_page\v!both
+ % \blank[\v!samepage,\v!strong]%
+ \nobreak
+ \else
+ % \blank[\v!preference,\v!weak]%
+ \allowbreak
+ \fi
+ \fi
+ \else
+ % \blank[\v!preference,\v!weak]%
+ \allowbreak % else no proper head split off
+ \fi}
+
+\unexpanded\def\tabl_ntb_inbetween
+ {\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax
+ \ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax
+ \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}%
+ \ifx\p_spaceinbetween\empty\else
+ \blank[\p_spaceinbetween]%
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_ntb_row_align_start_inject
+ {\bgroup % protect local vars
+ \m_tabl_ntb_before_split
+ \egroup
+ \ifenableTBLbreak
+ \tabl_ntb_before_page
+ \fi}
+
+\unexpanded\def\tabl_ntb_row_align_stop_inject
+ {\par
+ \nointerlineskip
+ \ifenableTBLbreak
+ \tabl_ntb_after_page
+ \fi
+ \bgroup % protect local vars
+ \m_tabl_ntb_after_split
+ \egroup
+ \bgroup % protect local vars
+ \tabl_ntb_inbetween
+ \egroup}
+
+\def\tabl_ntb_flush_content
+ {\the\everyTABLEpass
+ \global\c_tabl_ntb_spn\zerocount
+ \global\c_tabl_ntb_col\zerocount
+ \global\c_tabl_ntb_row\zerocount
+ \global\advance\c_tabl_ntb_row\minusone
+ \dostarttaggedchained\t!table\empty\??naturaltable
+ %\registerparoptions % (*) triggers max hsize
+ \the\t_tabl_ntb
+ \dostoptagged}
+
+\unexpanded\def\tabl_ntb_span#1%
+ {\hskip\tabl_ntb_get_dis\c_tabl_ntb_col
+ \dorecurse{#1}
+ {\hskip\tabl_ntb_get_wid\c_tabl_ntb_col\relax
+ \global\advance\c_tabl_ntb_col\plusone}}
+
+\unexpanded\def\tabl_ntb_skip#1%
+ {\global\advance\c_tabl_ntb_col#1\relax}
+
+\unexpanded\def\tabl_ntb_plus
+ {\global\advance\c_tabl_ntb_col\plusone
+ \kern\d_tabl_ntb_columndistance}
+
+\setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2%
+ {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
+ \ifnum\scratchcounter>\zerocount
+ \etoksapp\t_tabl_ntb_row
+ {\tabl_ntb_span{\the\scratchcounter}}%
+ \fi}
+
+\setvalue{\??naturaltablecell\the\c_tabl_ntb_cell}#1#2%
+ {\toksapp\t_tabl_ntb_row{\tabl_ntb_pass #1 #2 }% space delimited -> less tokens
+ \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
+ \ifnum\scratchcounter>\zerocount
+ \etoksapp\t_tabl_ntb_row
+ {\ifnum\scratchcounter=\plusone
+ \tabl_ntb_plus
+ \else
+ \tabl_ntb_skip{\the\scratchcounter}%
+ \fi}%
+ \fi}
+
+\unexpanded\def\tabl_ntb_cell#1#2%
+ {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}}
+
+\unexpanded\def\tabl_ntb_table_start
+ {\global\c_tabl_ntb_spn\zerocount
+ \global\c_tabl_ntb_row\zerocount
+ \global\c_tabl_ntb_col\zerocount
+ \c_tabl_tbl_pass\zerocount
+ \t_tabl_ntb\emptytoks}
+
+\def\tabl_ntb_pass_one#1 #2 %
+ {\tabl_ntb_get_txt{#1}{#2}}%
+
+\def\tabl_ntb_pass_two#1 #2 % meer in cellD
+ {\d_tabl_ntb_width\zeropoint
+ \scratchcounter\c_tabl_ntb_col
+ \!!counta\tabl_ntb_get_col{#1}{#2}\relax
+ \ifcase\!!counta\or
+ \advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \relax
+ \advance\scratchcounter\plusone
+ \else
+ \dorecurse\!!counta
+ {\advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \ifnum\recurselevel<\!!counta
+ +\d_tabl_ntb_columndistance
+ +\tabl_ntb_get_dis\scratchcounter
+ \fi
+ \relax
+ \advance\scratchcounter\plusone}%
+ \fi
+ \setbox\scratchbox\hbox{\tabl_ntb_get_txt{#1}{#2}}%
+ \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}%
+ %tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}%
+ \ifdim\ht\scratchbox>\tabl_ntb_get_hei{#1}\relax
+ \tabl_ntb_set_hei{#1}{\the\ht\scratchbox}%
+ \fi}%
+
+\def\tabl_ntb_pass_three#1 #2 %
+ {% height
+ \dostarttagged\t!tablecell\empty
+ \!!counta \tabl_ntb_get_col{#1}{#2}\relax
+ \!!countb \tabl_ntb_get_row{#1}{#2}\relax
+ \!!heighta\tabl_ntb_get_ht {#1}{#2}\relax
+ \tablecellcolumns\!!counta % used later so don't adapt these
+ \tablecellrows \!!countb % used later so don't adapt these
+ \d_tabl_ntb_height\zeropoint
+ \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax
+ % case: nc=maxcolumns
+ \else
+ \scratchcounter#1\relax
+ \dorecurse\!!countb
+ {\advance\d_tabl_ntb_height\tabl_ntb_get_hei\scratchcounter
+ \advance\scratchcounter\plusone}%
+ \ifdim\d_tabl_ntb_height<\!!heighta\relax
+ \d_tabl_ntb_height\!!heighta
+ \fi
+ \fi
+ % width
+ \d_tabl_ntb_width\zeropoint
+ \scratchcounter\c_tabl_ntb_col
+ \ifcase\!!counta\or
+ \advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \relax
+ \advance\scratchcounter\plusone
+ \else
+ \dorecurse\!!counta
+ {\advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \ifnum\recurselevel<\!!counta
+ +\d_tabl_ntb_columndistance
+ +\tabl_ntb_get_dis\scratchcounter
+ \fi
+ \relax
+ \advance\scratchcounter\plusone}%
+ \fi
+ % cell
+ \setbox\scratchbox\hbox attr \taggedattribute \attribute\taggedattribute \bgroup
+ \dotagTABLEsignal % maybe we need to add some packaging in this case
+ \tabl_ntb_get_txt{#1}{#2}%
+ \egroup
+ \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax
+ % case: nc=maxcolumns
+ \else
+ \scratchdimen\tabl_ntb_get_hei{#1}%
+ \setbox\scratchbox\hpack
+ {\lower\ht\scratchbox\hpack{\raise\scratchdimen\box\scratchbox}}%
+ \ht\scratchbox\scratchdimen
+ \fi
+ \dp\scratchbox\zeropoint
+ \edef\!!stringa{\tabl_ntb_get_ref{#1}{#2}}%
+ \ifx\!!stringa\empty
+ \box\scratchbox
+ \else
+ \normalexpanded{\noexpand\directgotobox{\box\scratchbox}[\!!stringa]}% to be checked
+ \fi
+ \dostoptagged} % right spot
+
+% \def\tabl_ntb_cell_finalize
+% {\doifnotinset\localwidth{\v!fit,\v!broad}% user set
+% {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
+% \ifdim\localwidth>\scratchdimen
+% \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}%
+% \fi}}
+
+\def\tabl_ntb_cell_finalize
+ {\ifx\localwidth\v!fit
+ % nothing
+ \orelse\ifx\localwidth\v!broad
+ % nothing
+ \orelse\ifx\localwidth\empty
+ % nothing (safeguard)
+ \else
+ \tabl_ntb_cell_finalize_indeed
+ \fi}
+
+\def\tabl_ntb_cell_finalize_indeed
+ {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
+ \ifdim\localwidth>\scratchdimen
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}%
+ \fi}
+
+\let\tabl_ntb_preroll\relax
+
+\def\tabl_ntb_table_get_max_width
+ {\scratchdimen\wd\scratchbox\relax}
+
+% enable dper 2018-02-22
+
+\def\tabl_ntb_table_get_max_width_step
+ {\advance\scratchdimen\tabl_ntb_get_wid\fastloopindex
+ \advance\scratchdimen\tabl_ntb_get_dis\fastloopindex}
+
+\def\tabl_ntb_table_get_max_width
+ {\scratchdimen\zeropoint
+ \dofastloopcs\c_tabl_ntb_maximum_col\tabl_ntb_table_get_max_width_step
+ \ifdim\scratchdimen<\wd\scratchbox\relax
+ \scratchdimen\wd\scratchbox\relax
+ \fi}
+
+\def\tabl_ntb_table_stop
+ {\forgetall % new, here see narrower-004.tex
+ %\setbox\scratchbox\hbox
+ % {\letnaturaltablelocalparameter\c!frame\v!off
+ % \letnaturaltablelocalparameter\c!background\empty
+ % \letnaturaltablelocalparameter\c!align\v!no
+ % \inheritednaturaltablelocalframed{\strut}}%
+ %\edef\minimalcellheight{\the\ht\scratchbox}% not used
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\tabl_ntb_let_aut\recurselevel\zeropoint
+ % new
+ \c_tabl_ntb_current_col_one\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_row
+ {%tabl_ntb_let_wd\recurselevel\c_tabl_ntb_current_col_one\zeropoint
+ \tabl_ntb_let_ht\recurselevel\c_tabl_ntb_current_col_one\zeropoint}%
+ % till here
+ \tabl_ntb_let_tal\recurselevel\zerocount
+ \tabl_ntb_let_wid\recurselevel\zeropoint
+ \tabl_ntb_let_dis\recurselevel\zeropoint}%
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_let_hei\recurselevel\maxdimen}%
+ \tabl_ntb_let_gal\zerocount
+ \tabl_ntb_preroll\relax
+ \c_tabl_tbl_pass\plusone
+ \let\tabl_ntb_pass\tabl_ntb_pass_one
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \ifcase\tabl_ntb_get_gal\or
+ % \c_tabl_tbl_pass\plusone
+ % \let\tabl_ntb_pass\tabl_ntb_pass_one
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a_extra
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \fi
+ \tabl_ntb_let_dis\c_tabl_ntb_maximum_col\zeropoint
+ %
+ \tabl_ntb_table_get_max_width % \scratchdimen\scratchbox
+ %
+ \ifautoTBLspread
+ % experimental, stretch non fixed cells to \hsize
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \tabl_ntb_stretch_widths
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ % \orelse\ifdim\wd\scratchbox>\hsize
+ \orelse\ifdim\scratchdimen>\hsize
+ \ifautoTBLhsize
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \fi
+ \orelse\ifautoTBLrowspan
+ \ifnum\c_tabl_ntb_maximum_row_span>\plusone % max ?
+ % added jan 2002 because nx=* did no longer work
+ \ifnum\c_tabl_ntb_encountered_max<\c_tabl_ntb_maximum_col
+ % added jun 2014 because someone had less columns than nx .. sigh / see *nx*
+ \writestatus\m!TABLE{missing\space\number\numexpr\c_tabl_ntb_maximum_col-\c_tabl_ntb_encountered_max\relax\space column(s), guessing widths}%
+ \fi
+ \edef\savedhsize{\the\hsize}%
+ % \hsize\wd\scratchbox\relax % new per 17/04/2006
+ \hsize\scratchdimen\relax % new per 17/04/2006
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \hsize\savedhsize
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_c
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \fi
+ \fi
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_d
+ \c_tabl_tbl_pass\plustwo
+ \let\tabl_ntb_pass\tabl_ntb_pass_two
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \tabl_ntb_check_heights_one
+ \tabl_ntb_check_heights_two
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_e
+ \c_tabl_tbl_pass\plusthree
+ \let\tabl_ntb_pass\tabl_ntb_pass_three
+ \ifnum\m_tabl_tbl_level>\plusone
+ \tabl_tbl_split_nop
+ \orelse\ifenableTBLbreak
+ \tabl_tbl_split_yes
+ \else
+ \tabl_tbl_split_nop
+ \fi}
+
+\def\tabl_ntb_stretch_widths % more variants, e.g. a max to \dimend
+ {\ifcase\c_tabl_ntb_maximum_col\else % else division by zero
+ \!!dimend\zeropoint
+ \!!dimene\dimexpr
+ \hsize
+ -\d_tabl_ntb_leftmargindistance
+ -\d_tabl_ntb_rightmargindistance
+ +\d_tabl_ntb_columndistance
+ \relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\advance\!!dimend\dimexpr
+ \tabl_ntb_get_wid\recurselevel
+ \relax
+ \advance\!!dimene\dimexpr
+ -\tabl_ntb_get_dis\recurselevel
+ -\d_tabl_ntb_columndistance
+ \relax}%
+ \relax
+ % distribute width (stretch)
+ \ifdim\!!dimend<\!!dimene
+ \advance\!!dimend-\!!dimene
+ \divide\!!dimend\c_tabl_ntb_maximum_col
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\tabl_ntb_set_wid\recurselevel{\the\dimexpr\tabl_ntb_get_wid\recurselevel-\!!dimend\relax}}%
+ \fi
+ \fi}
+
+\def\tabl_tbl_split_nop
+ {\setbox\b_tabl_ntb_final\vbox{\tabl_ntb_flush_content}%
+ \postprocessTABLEbox\b_tabl_ntb_final
+ \beforeTABLEbox
+ % packaging prevents max hsized box
+ % \hbox{\registerparoptions\box\b_tabl_ntb_final}% (*) better here
+ % better :
+ \ifinsidefloat
+ % no \dontleavehmode else too wide, otherwise we get a \hsized box
+ \else
+ \registerparoptions % (*) better here (also does a \dontleavehmode)
+ \ifhmode\else\dontleavehmode\fi
+ \fi
+ \box\b_tabl_ntb_final
+ \afterTABLEbox}
+
+\def\tabl_tbl_split_yes
+ {\ifinsidesplitfloat
+ \donetrue
+ \orelse\ifinsidefloat
+ \donefalse
+ \else
+ \donetrue
+ \fi
+ \ifdone
+ \expandafter\tabl_ntb_split_box
+ \else
+ \expandafter\tabl_tbl_split_nop
+ \fi}
+
+\newbox\TABLEsplitbox % public, don't change
+
+\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox
+
+\def\tabl_ntb_split_box
+ {\resettsplit
+ \def\tsplitminimumfreelines{2}%
+ \def\tsplitminimumfreespace{\dimexpr\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset\relax}%
+ \def\tsplitbeforeresult {\beforeTABLEsplitbox}%
+ \def\tsplitafterresult {\afterTABLEsplitbox}%
+ \def\tsplitafter {\m_tabl_ntb_after_split}%
+ \def\tsplitbefore {\m_tabl_ntb_before_split}% supported ?
+ \setbox\tsplitcontent\vbox{\tabl_ntb_flush_content}%
+ \ifmultipleTBLheads
+ \dorecurse\c_tabl_ntb_n_of_head_lines
+ {\setbox\scratchbox\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplithead\vbox{\unvcopy\tsplithead\unvcopy\scratchbox}}% \vpack ?
+ \dorecurse\c_tabl_ntb_n_of_next_lines
+ {\setbox\scratchbox\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplitnext\vbox{\unvcopy\tsplitnext\unvcopy\scratchbox}}% \vpack ?
+ \fi
+ \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}%
+ \ifx\p_spaceinbetween\empty\else
+ \blank[\p_spaceinbetween]%
+ \fi
+ \def\postprocesstsplit{\postprocessTABLEsplitbox{\box\tsplitresult}}%
+ \handletsplit}
+
+% ! ! ! ! TODO: naast \postprocessTABLEsplitbox ook evt \postprocessTABLEbox voor niet split
+
+\let\postprocessTABLEsplitbox\gobbleoneargument
+\let\postprocessTABLEbox \gobbleoneargument
+
+\let\beforeTABLEsplitbox\relax
+\let\afterTABLEsplitbox \relax
+\let\beforeTABLEbox \relax
+\let\afterTABLEbox \relax
+
+\def\tabl_ntb_check_widths_one{\tabl_ntb_check_widths_indeed\zerocount} % 0 = trial run
+\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed\plusone } % 1 = real run
+
+\def\tabl_ntb_check_widths_indeed#1%
+ {\ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths B#1\fi
+ \!!counta\zerocount
+ \!!dimena\dimexpr
+ \hsize
+ -\d_tabl_ntb_leftmargindistance
+ -\d_tabl_ntb_rightmargindistance
+ -\d_tabl_ntb_columndistance
+ \relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_aut\recurselevel\relax
+ \advance\!!dimena\dimexpr
+ -\tabl_ntb_get_dis\recurselevel
+ -\d_tabl_ntb_columndistance
+ \relax
+ \ifdim\scratchdimen>\zeropoint\relax
+ \advance\!!dimena -\scratchdimen
+ \else
+ \scratchdimen\tabl_ntb_get_wid\recurselevel\relax
+ \ifdim\scratchdimen>\d_tabl_ntb_maxwidth\relax
+ \ifcase#1\else\tabl_ntb_let_wid\recurselevel\zeropoint\fi
+ \advance\!!counta \plusone
+ \orelse\ifdim\scratchdimen>\zeropoint\relax
+ \advance\!!dimena -\scratchdimen
+ \else
+ % eigenlijk moet dit alleen als de kolom wordt overspannen door een
+ % vorige, maw extra dubbele loop en status var
+ \ifnum\c_tabl_ntb_encountered_max=\c_tabl_ntb_maximum_col % *nx* bah
+ \advance\!!counta \plusone % setting maxwidth to a large value also works
+ \fi
+ \fi
+ \fi}%
+ \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths M#1\fi
+ \ifcase\!!counta \else \divide\!!dimena \!!counta \fi
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax
+ \ifcase#1\relax
+ \ifdim\scratchdimen<\!!dimena % take natural width
+ \tabl_ntb_set_aut\recurselevel{\the\scratchdimen}%
+ \fi
+ \else
+ \ifdim\scratchdimen=\zeropoint % auto set width
+ \tabl_ntb_set_wid\recurselevel{\the\!!dimena}%
+ \fi
+ \fi}%
+ \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths E#1\fi}
+
+% todo: use scratchcounters, not !! ones
+
+\def\tabl_ntb_check_heights_one_indeed
+ {\!!countb\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax
+ % check row span
+ \ifnum\!!countb>\plusone
+ % current height in row
+ \dimen0=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three
+ % find nearest height in row
+ \dimen2=\zeropoint
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\recurselevel\endcsname
+ \!!countc=\tabl_ntb_get_row\c_tabl_ntb_current_row_three\recurselevel\relax
+ \ifnum\!!countc=\plusone
+ \dimen4=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\recurselevel\relax
+ \ifdim\dimen2<\dimen4
+ \dimen2=\dimen4
+ \fi
+ \fi
+ \fi
+ \fi}%
+ \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
+ % calculate cummulative height
+ \dimen4=\dimen2
+ \!!countc\c_tabl_ntb_current_row_three
+ \advance\!!countc\minusone
+ \dorecurse\!!countb
+ {\ifnum\c_tabl_ntb_current_row_four=\c_tabl_ntb_current_row_three\else
+ \advance\dimen4 \tabl_ntb_get_hei\c_tabl_ntb_current_row_four
+ \fi
+ \ifnum\recurselevel=\!!countb\else
+ \tabl_ntb_set_nob\!!countc
+ \advance\!!countc\plusone
+ \fi
+ \advance\c_tabl_ntb_current_row_four\plusone}%
+ % distribute overshoot equally
+ \ifdim\dimen2>\zeropoint % new: test on natural-003
+ \ifdim\dimen4<\dimen0
+ \advance\dimen0 -\dimen4
+ \divide\dimen0 \!!countb
+ \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}%
+ \dorecurse\!!countb
+ {\dorecurse\c_tabl_ntb_maximum_col
+ {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else
+ \scratchdimen\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row_four\recurselevel+\dimen0\relax
+ \tabl_ntb_set_ht\c_tabl_ntb_current_row_four\recurselevel{\the\scratchdimen}%
+ \ifdim\tabl_ntb_get_hei\c_tabl_ntb_current_row_four<\scratchdimen
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_four{\the\scratchdimen}%
+ \fi
+ \fi}%
+ \advance\c_tabl_ntb_current_row_four\plusone}%
+ \orelse\ifdim\dimen4>\dimen0
+ \iftightTBLrowspan
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}%
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\def\tabl_ntb_check_heights_one
+ {\dorecurse\c_tabl_ntb_maximum_row
+ {\c_tabl_ntb_current_row_three\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\c_tabl_ntb_current_col_three\recurselevel\relax
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\endcsname
+ \tabl_ntb_check_heights_one_indeed
+ \fi}}}
+
+\def\tabl_ntb_check_heights_two
+ {}
+
+\def\tabl_ntb_show_widths#1#2%
+ {\begingroup
+ \scratchdimen\zeropoint
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\advance\scratchdimen\tabl_ntb_get_wid\recurselevel\relax}%
+ \writestatus\m!TABLE{#1 \ifcase#2trial\else real\fi: hsize: \the\hsize, total: \the\scratchdimen}%
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\writestatus\m!TABLE{\space\space\recurselevel: \the\dimexpr\tabl_ntb_get_wid\recurselevel}}%
+ \endgroup}
+
+\def\tabl_ntb_char_align % called often
+ {\edef\p_characteralign{\naturaltablelocalparameter\c!aligncharacter}%
+ \ifx\p_characteralign\v!yes
+ \ifcase\c_tabl_tbl_pass\or
+ \tabl_ntb_let_tal\currentTABLEcolumn\plusone
+ \tabl_ntb_let_gal\plusone
+ \fi
+ \expandafter\tabl_ntb_char_align_indeed
+ \else
+ \expandafter\gobbletwoarguments
+ \fi}
+
+\def\tabl_ntb_char_align_indeed#1#2% row column
+ {\ifcase\c_tabl_tbl_pass \or
+ \setcharacteralign{#2}{\naturaltablelocalparameter\c!alignmentcharacter}% we could store the character in tal
+ \fi
+ \typo_charalign_adapt_font
+ \signalcharacteralign{#2}{#1}}
+
+\unexpanded\def\tabl_ntb_cell_process_a_extra#1#2%
+ {\ifcase\tabl_ntb_get_tal{#2}\relax
+ \expandafter\tabl_ntb_cell_process_x
+ \else
+ \expandafter\tabl_ntb_cell_process_a
+ \fi{#1}{#2}}
+
+\unexpanded\def\tabl_ntb_cell_process_x#1#2[#3]#4%
+ {}
+
+% problem: when span doesn't break we can have a span that is the sum of cells but
+% still to small .. chicken egg problem ... for that we should also have a smallest
+% width run
+%
+% nilling the background makes a run upto 25% faster
+
+\def\tabl_ntb_cell_process_a_check_span_one
+ {\ifautosqueezeTBLspan
+ \edef\p_width{\naturaltablelocalparameter\c!width}%
+ \ifcsname\??naturaltablesqueeze\p_width\endcsname\lastnamedcs\else\donefalse\fi
+ \else
+ \donetrue
+ \fi
+ \ifdone % brr, 0
+ \ifnum\scratchcounter>\plusone
+ \tabl_ntb_set_spn\c_tabl_ntb_col
+ \fi
+ \fi}
+
+\let\tabl_ntb_cell_process_a_check_span_two_yes\relax
+
+\def\tabl_ntb_cell_process_a_check_span_two_nop
+ {\ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
+ \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
+ \fi}
+
+\unexpanded\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! !
+ {\bgroup
+ \letnaturaltablelocalparameter\c!option\empty
+ \tabl_ntb_setup_cell{#1}{#2}%
+ \setupcurrentnaturaltablelocal[#3]%
+ \letnaturaltablelocalparameter\c!background\empty
+ \letnaturaltablelocalparameter\c!frame\v!off
+ \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
+ \setbox\scratchbox\hbox
+ {\scratchdimen\naturaltablelocalparameter\c!distance\relax
+ \ifdim\scratchdimen>\tabl_ntb_get_dis{#2}\relax
+ \tabl_ntb_set_dis{#2}{\the\scratchdimen}%
+ \fi
+ \anch_backgrounds_text_level_start
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}%
+ \anch_backgrounds_text_level_stop
+ \ifcase\c_anch_backgrounds_text_count\else
+ \tabl_ntb_let_bck{#1}{#2}\c_anch_backgrounds_text_state
+ \fi
+ }%
+ \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
+ \ifdim\wd\scratchbox>\scratchdimen
+ \ifsqueezeTBLspan
+ \tabl_ntb_cell_process_a_check_span_one
+ \fi
+ \tabl_ntb_spn_doifelse\c_tabl_ntb_col
+ \tabl_ntb_cell_process_a_check_span_two_yes
+ \tabl_ntb_cell_process_a_check_span_two_nop
+ \fi
+ \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
+ \ifdim\ht\scratchbox<\scratchdimen
+ \tabl_ntb_set_hei\scratchcounter{\the\ht\scratchbox}% auto set
+ \fi
+ \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}%
+ %tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}%
+ \ifautoTBLcheckwidth
+ \ifdim\wd\scratchbox<.75\hsize % fuzzy guess
+ \ifdim\ht\scratchbox>2\openlineheight % honor width since this
+ \scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax % can be a figure or so
+ \ifdim\scratchdimen=\zeropoint
+ % side effect: when width is set to 0pt,
+ % we can force a span that fits the sum of spans widths
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\scratchdimen}%
+ \orelse\ifdim\wd\scratchbox>\scratchdimen
+ % unless span
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\wd\scratchbox}%
+ % to be translated
+ \writestatus\m!TABLE{no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \setbox\scratchboxone\emptyhbox
+ \wd\scratchboxone\wd\scratchbox
+ \ht\scratchboxone\ht\scratchbox
+ \dp\scratchboxone\dp\scratchbox
+ \box\scratchboxone
+ \egroup}
+
+\unexpanded\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5%
+ {\setbox\scratchbox\hbox
+ {\tabl_ntb_setup_cell{#2}{#3}%
+ \setupcurrentnaturaltablelocal[#4,#1]%
+ \letnaturaltablelocalparameter\c!background\empty
+ \letnaturaltablelocalparameter\c!frame\v!off
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start#5\tabl_ntb_cell_stop}}%
+ \setbox2\emptyhbox % todo: \scratchboxtwo
+ \wd2\wd\scratchbox
+ \ht2\ht\scratchbox
+ \dp2\dp\scratchbox
+ \ifautoTBLrowspan
+ \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \ifcsname\tabl_ntb_row_pattern\scratchcounter\c_tabl_ntb_col\endcsname
+ \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
+ \ifnum\tabl_ntb_get_row\scratchcounter\c_tabl_ntb_col>\plusone
+ \ifdim\ht\scratchbox>\scratchdimen
+ \ht2\dimexpr-\scratchdimen-\ht\scratchbox\relax
+ \fi
+ \fi
+ \fi
+ \fi
+ \box2 }
+
+\unexpanded\def\tabl_ntb_cell_process_b#1#2[#3]#4%
+ {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
+ \ifdim\scratchdimen>\zeropoint\relax
+ \else
+ \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
+ \ifdim\scratchdimen>\zeropoint\relax
+ \ifnum\tabl_ntb_get_col{#1}{#2}=\c_tabl_ntb_maximum_col\relax
+ \scratchdimen\hsize
+ \fi
+ \fi
+ \fi
+ \normalexpanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}%
+ {#1}{#2}[#3]{\tabl_ntb_char_align{#1}{#2}#4}}
+
+\unexpanded\def\tabl_ntb_cell_process_c
+ {\tabl_ntb_cell_process_b_c{}}
+
+\unexpanded\def\tabl_ntb_cell_process_d#1#2[#3]#4%
+ {\tabl_ntb_setup_cell{#1}{#2}%
+ \bgroup
+ \setupcurrentnaturaltablelocal[#3]%
+ \letnaturaltablelocalparameter\c!background\empty
+ \letnaturaltablelocalparameter\c!frame\v!off
+ \setnaturaltablelocalparameter\c!width{\d_tabl_ntb_width}%
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}%
+ \egroup}
+
+\unexpanded\def\tabl_ntb_cell_process_e#1#2[#3]#4%
+ {\tabl_ntb_setup_cell{#1}{#2}%
+ \setupcurrentnaturaltablelocal[#3]% to get the color right, the way we
+ \color % handle color here prevents interference due to whatsit nodes
+ [\naturaltablelocalparameter\c!color] % as well as permits local colors to take precedence
+ {\letnaturaltablelocalparameter\c!color\empty
+ \setnaturaltablelocalparameter\c!width{\d_tabl_ntb_width}%
+ \ifdim\d_tabl_ntb_height=\zeropoint\relax % case: nc=maxcolumns
+ \else
+ \setnaturaltablelocalparameter\c!height{\d_tabl_ntb_height}%
+ \fi
+ \ifcase\c_anch_backgrounds_text_count\else
+ \edef\p_region{\naturaltablelocalparameter\c!region}%
+ \ifx\p_region\empty\ifnum\tabl_ntb_get_bck{#1}{#2}>\zerocount
+ \letnaturaltablelocalparameter\c!region\v!yes
+ \fi\fi
+ \fi
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}}%
+ \hskip\tabl_ntb_get_dis{#2}}
+
+\newtoks\everyresetTABLEyes
+\newtoks\everyresetTABLEnop
+
+\appendtoks
+ \setupTABLE [%
+ %
+ % framed defaults
+ %
+ \c!width=\v!fit,%
+ \c!height=\v!fit,%
+ \c!lines=,%
+ \c!offset=.25\exheight,%
+ \c!empty=\v!no,%
+ \c!frame=\v!on,%
+ \c!topframe=,%
+ \c!bottomframe=,%
+ \c!leftframe=,%
+ \c!rightframe=,%
+ \c!radius=.5\bodyfontsize,%
+ \c!rulethickness=\linewidth,%
+ \c!corner=\v!rectangular,%
+ \c!depth=\zeropoint,%
+ \c!foregroundcolor=,%
+ \c!foregroundstyle=,%
+ \c!background=,%
+ \c!backgroundcolor=,%
+ \c!backgroundoffset=\v!frame,%
+ \c!framecolor=,%
+ \c!frameoffset=.5\linewidth,%
+ % \c!backgroundcorner=\framedparameter\c!corner,%
+ % \c!backgrounddepth=\framedparameter\c!depth,%
+ % \c!backgroundradius=\framedparameter\c!radius,%
+ % \c!framecorner=\framedparameter\c!corner,%
+ % \c!framedepth=\framedparameter\c!depth,%
+ % \c!frameradius=\framedparameter\c!radius,%
+ \c!component=,%
+ \c!region=,%
+ \c!align=,%
+ \c!bottom=\vss,%
+ \c!top=,%
+ \c!strut=\v!yes,%
+ \c!autostrut=\v!no,%
+ \c!location=\v!normal,%
+ \c!orientation=,%
+ \c!autowidth=\v!yes,%
+ \c!setups=,%
+ \c!loffset=\zeropoint,%
+ \c!roffset=\zeropoint,%
+ \c!toffset=\zeropoint,%
+ \c!boffset=\zeropoint,%
+ %
+ % table specific
+ %
+ \c!aligncharacter=\v!no,%
+ \c!alignmentcharacter={,},%
+ \c!color=,%
+ \c!columndistance=\zeropoint,% each column (whole table)
+ \c!distance=\zeropoint,% individual column
+ \c!headcolor=,%
+ \c!header=,%
+ \c!headstyle=\v!bold,%
+ \c!left=,%
+ \c!leftmargindistance=\zeropoint,% whole table
+ \c!maxwidth=8\emwidth,%
+ \c!option=,% \v!stretch
+ \c!right=,%
+ \c!rightmargindistance=\zeropoint,% whole table
+ \c!spaceinbetween=,%
+ \c!split=\v!auto,%
+ \c!splitoffset=\zeropoint,%
+ \c!style=,%
+ \c!textwidth=\v!local,% was \hsize
+ ]%
+\to \everyresetTABLEyes
+
+\appendtoks
+ \setupTABLE [%
+ \c!width=\v!fit,%
+ \c!height=\v!fit%
+ ]%
+\to \everyresetTABLEnop
+
+\the\everyresetTABLEyes
+
+% \bgroup
+% \setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}]
+% \bTABLE
+% \bTR \bTD 1,2 \eTD \bTD 2 \eTD \eTR
+% \bTR \bTD 11,2 \eTD \bTD
+% {\setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}]
+% \bTABLE
+% \bTR \bTD 1,2 \eTD \bTD 2 \eTD \eTR
+% \bTR \bTD 11,22 \eTD \bTD 2 \eTD \eTR
+% \bTR \bTD 11,2 \eTD \bTD 2 \eTD \eTR \eTABLE} \eTD \eTR
+% \bTR \bTD 11,22 \eTD \bTD 2 \eTD \eTR
+% \eTABLE
+% \egroup
+
+\newconditional\resetTABLEmode \settrue\resetTABLEmode
+
+\def\tabl_ntb_parameters_reset % we can use setters instead
+ {\ifnum\m_tabl_tbl_level>\plusone % in ieder geval
+ \ifconditional\resetTABLEmode
+ \the\everyresetTABLEyes
+ \else
+ \the\everyresetTABLEnop
+ \fi
+ \fi}
+
+% new (for Olivier Turlier)
+%
+% \defineTABLEsetup [xx] [foregroundcolor=red]
+%
+% \bTABLE
+% \bTR \bTD oeps \eTD \bTD oeps \eTD \eTR
+% \bTR \bTDs[xx] oeps \eTDs \bTD oeps \eTD \eTR
+% \bTRs[xx] \bTD oeps \eTD \bTD oeps \eTD \eTRs
+% \eTABLE
+
+\installcorenamespace{naturaltablesetup}
+
+\unexpanded\def\defineTABLEsetup
+ {\dodoubleargument\tabl_ntb_define_setup}
+
+\def\tabl_ntb_define_setup[#1][#2]%
+ {\setvalue{\??naturaltablesetup#1}{#2}}
+
+\let\eTDs\relax
+\let\eTRs\relax
+
+\unexpanded\def\bTDs[#1]#2\eTDs
+ {\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD}
+
+\unexpanded\def\bTRs[#1]#2\eTRs
+ {\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR}
+
+\protect \endinput
+
+% todo: mode: first|next (of niets)
diff --git a/tex/context/base/mkiv/tabl-tbl.mkxl b/tex/context/base/mkiv/tabl-tbl.mkxl
new file mode 100644
index 000000000..dc8ae0214
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-tbl.mkxl
@@ -0,0 +1,3022 @@
+%D \module
+%D [ file=core-tbl,
+%D version=1998.11.03,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Text Flow Tabulation,
+%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.
+
+\writestatus{loading}{ConTeXt Table Macros / Tabulation}
+
+\unprotect
+
+\registerctxluafile{tabl-tbl}{} % experiment
+
+%D I can probably reimplement this using a \LUATEX\ combination but it does not pay
+%D of in development time. If I need something else I will write it from scratch
+%D anyway. This module looks a bit complex which is a consequence of it dealing with
+%D paragraphs being split over pages and that there are several passes over the data
+%D set. We can probably do some cleanup (combine/split).
+%D
+%D Caching the preamble does not save much (compared to other bits and pieces of
+%D \CONTEXT). There are not that many ways to deal with preambles and this is just
+%D one of them. The keys are somewhat similar to those of the \TABLE\ package.
+
+% |p2|p3| 2:3 -> spanning (maybe)
+%
+% In-text tabbing environment
+%
+% \starttabulate[| separated template] % eg [|l|p|] or [|l|p|p|]
+% \NC ... \NC ... \NC\NR
+% \stoptabulate
+%
+% with: two pass auto width calculation when no p-width
+% specified, even with multiple p's, see examples.
+%
+% TaBlE compatible specifications:
+%
+% l align column/paragraph left
+% r align column/paragraph right
+% c align column/paragraph center
+% p p(dimen) of automatisch als alleen p
+% w column width
+% f font#1
+% A {alignmentoptions}
+% B bold
+% I italic
+% S slanted
+% T type
+% R roman
+% m math
+% M display math
+% h hook (inner level or par lines)
+% b before (may be command#1)
+% a after
+% i i<n> skip left of column
+% j i<n> skip right of column
+% k i<n> skip around column
+% d digits (~)
+%
+% C [LMRT] {color} % T is text color
+%
+% | {color,n}
+%
+% s setups
+%
+% g g{char} align at char
+% . align at .
+% , align at ,
+%
+% Still to be done
+%
+% N math numbers (best hook into existing digits mechanism)
+% n numbers (best hook into existing digits mechanism)
+% Q math numbers (best hook into existing digits mechanism)
+% q numbers (best hook into existing digits mechanism)
+% ~ \hskip.5em
+% | check
+%
+% nesting
+%
+% 10 evt auto stack; dan wel andere signal dan void nodig
+%
+% present but not yet 100% ok
+%
+% \TL [width,color] bottom hrule
+% \FL [width,color] first hrule
+% \ML [width,color] mid hrule (with auto split)
+% \LL [width,color] bottom hrule
+% \BL [width,color] last hrule
+%
+% \HL [width,color] top rule
+% \VL [width,color]
+%
+% \CC \CL \CM \CR color
+%
+% \EQ \RQ \HQ equal (raw, hook)
+% \NC \RC \HC normal (raw, hook)
+%
+% \NR checked break
+% \NB no break
+%
+% \HR : rule with lineheight
+%
+% \autotabulaterule : with lineheight, not first/last
+% \autotabulateline : spaced, not first/last
+% \tabulaterule : with lineheight
+% \tabulateline : spaced
+%
+% tricky: align scans ahead, over # and expands ones before
+% while doing
+%
+% new:
+%
+% \starttabulate[|cg{.}|cg{,}|cg{,}|]
+% \NC period \NC comma \NC comma \NC\NR
+% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR
+% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR
+% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
+% \NG 10 \NG 10 \NG 0,00 \NC\NR
+% \stoptabulate
+%
+% \starttabulate[|c.|c,|c,|]
+% \NC period \NC comma \NC comma \NC\NR
+% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR
+% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR
+% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
+% \NG 10 \NG 10 \NG 0,00 \NC\NR
+% \stoptabulate
+
+% nice demo (for BG)
+%
+% \starttabulate[|r|b{$\star$}|ra{\percent}|b{=}|r|]
+% \NC 500 \NC \NC 60 \NC \NC 300 \NC \NR
+% \NC 500 \NC \NC 55 \NC \NC 275 \NC \NR
+% \NC 500 \NC \NC 50 \NC \NC 250 \NC \NR
+% \NC 500 \NC \NC 45 \NC \NC 225 \NC \NR
+% \NC 500 \NC \NC 40 \NC \NC 200 \NC \NR
+% \NC 500 \NC \NC 35 \NC \NC 175 \NC \NR
+% \NC 500 \NC \NC 30 \NC \NC 150 \NC \NR
+% \NC 500 \NC \NC 25 \NC \NC 125 \NC \NR
+% \NC 500 \NC \NC 20 \NC \NC 100 \NC \NR
+% \stoptabulate
+
+\newtoks \t_tabl_tabulate_preamble
+\newtoks \t_tabl_tabulate_before
+\newtoks \t_tabl_tabulate_after
+\newtoks \t_tabl_tabulate_bmath
+\newtoks \t_tabl_tabulate_emath
+\newtoks \t_tabl_tabulate_font
+\newtoks \t_tabl_tabulate_settings
+\newtoks \t_tabl_tabulate_dummy
+\newtoks \t_tabl_tabulate_every_row
+\newtoks \t_tabl_tabulate_every_after_row
+\newtoks \t_tabl_tabulate_every_real_row
+
+\newtoks \t_tabl_tabulate_initializers_first
+\newtoks \t_tabl_tabulate_initializers_second
+
+\newcount \c_tabl_tabulate_nofauto
+\newcount \c_tabl_tabulate_columns
+\newcount \c_tabl_tabulate_column
+\newcount \c_tabl_tabulate_plines_min
+\newcount \c_tabl_tabulate_plines_max
+\newcount \c_tabl_tabulate_max_colorcolumn
+\newcount \c_tabl_tabulate_max_vrulecolumn
+\newcount \c_tabl_tabulate_repeathead
+\newcount \c_tabl_tabulate_noflines
+\newcount \c_tabl_tabulate_totalnoflines
+\newcount \c_tabl_tabulate_minusnoflines
+\newcount \c_tabl_tabulate_align
+\newcount \c_tabl_tabulate_nofrealrows
+\newcount \c_tabl_tabulate_autocolor
+
+\newcount \c_tabl_tabulate_nofcolumns % set at the lua end by parser
+\newcount \c_tabl_tabulate_has_rule_spec_first % set at the lua end by parser (for the moment a count)
+\newcount \c_tabl_tabulate_has_rule_spec_last % set at the lua end by parser (for the moment a count)
+
+\newconditional \c_tabl_tabulate_nopbreak
+\newconditional \c_tabl_tabulate_firstflushed
+\newconditional \c_tabl_tabulate_equal
+\newconditional \c_tabl_tabulate_split \settrue\c_tabl_tabulate_split
+\newconditional \c_tabl_tabulate_automode
+\newconditional \c_tabl_tabulate_handlepbreak \settrue\c_tabl_tabulate_handlepbreak
+\newconditional \c_tabl_tabulate_autorulespacing \settrue\c_tabl_tabulate_autorulespacing
+\newconditional \c_tabl_tabulate_someamble
+\newconditional \c_tabl_tabulate_tolerant_break
+\newconditional \c_tabl_tabulate_splitoff_whitespace
+\newconditional \c_tabl_tabulate_pwidth_set
+\newconditional \c_tabl_tabulate_reshape
+
+\newdimen \d_tabl_tabulate_width_p
+\newdimen \d_tabl_tabulate_width_w
+\newdimen \d_tabl_tabulate_width
+\newdimen \d_tabl_tabulate_unit
+\newdimen \d_tabl_tabulate_height_p_max
+\newdimen \d_tabl_tabulate_vrulethickness_default
+\newdimen \d_tabl_tabulate_hrulethickness_default
+\newdimen \d_tabl_tabulate_vrulethickness
+\newdimen \d_tabl_tabulate_hrulethickness % not used
+\newdimen \d_tabl_tabulate_vrulethickness_local
+\newdimen \d_tabl_tabulate_hrulethickness_local
+\newdimen \d_tabl_tabulate_indent
+\newdimen \d_tabl_tabulate_splitoff_betweenskip
+\newdimen \d_tabl_tabulate_margin
+
+\newskip \s_tabl_tabulate_pre
+\newskip \s_tabl_tabulate_post
+\newskip \s_tabl_tabulate_first
+\newskip \s_tabl_tabulate_last
+\newskip \s_tabl_tabulate_separator
+
+\newbox \b_tabl_tabulate
+
+\newconstant \c_tabl_tabulate_pass
+\newconstant \c_tabl_tabulate_type
+\newconstant \c_tabl_tabulate_kind % 1=strong 2=equals
+\newconstant \c_tabl_tabulate_splitlinemode \c_tabl_tabulate_splitlinemode\plusone
+\newconstant \c_tabl_tabulate_colorspan
+\newconstant \c_tabl_tabulate_localcolorspan
+\newconstant \c_tabl_tabulate_modus
+
+\let\tabulatesplitlinemode\c_tabl_tabulate_splitlinemode % temp hack, we need an interface
+
+\let \m_tabl_tabulate_separator_factor \empty % fraction
+
+\newtoks \everytabulatepar % where used ?
+\newtoks \everytabulate % public ?
+
+\unexpanded\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles !
+\unexpanded\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated
+
+\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty
+
+\installcorenamespace{tabulatebox}
+\installcorenamespace{tabulatesetup}
+\installcorenamespace{tabulatehook}
+\installcorenamespace{tabulatesplit}
+\installcorenamespace{tabulateseparator}
+\installcorenamespace{tabulatecolor}
+\installcorenamespace{tabulateheader}
+\installcorenamespace{tabulatealigning}
+\installcorenamespace{tabulatepreamble}
+\installcorenamespace{tabulatevrule}
+
+\installcorenamespace{tabulatehead}
+\installcorenamespace{tabulatefoot}
+\installcorenamespace{tabulatenext}
+
+\prependtoks
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+\to \t_tabl_tabulate_initializers_first
+
+\prependtoks
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+\to \t_tabl_tabulate_initializers_second
+
+\prependtoks
+ \global\advance\c_tabl_tabulate_nofrealrows\plusone
+\to \t_tabl_tabulate_every_real_row
+
+\def\b_tabl_tabulate_current#1%
+ {\csname\??tabulatebox\number#1\endcsname} % beware, a synonym
+
+\def\tabl_tabulate_initialize_boxes#1%
+ {\scratchcounter#1\relax
+ \tabl_tabulate_initialize_boxes_step}
+
+\def\tabl_tabulate_initialize_boxes_step
+ {\ifnum\scratchcounter>\zerocount
+ \tabl_tabulate_initialize_box\scratchcounter
+ \advance\scratchcounter\minusone
+ \expandafter\tabl_tabulate_initialize_boxes_step
+ \fi}
+
+\def\tabl_tabulate_initialize_box#1% also used elsewhere
+ {\ifcsname\??tabulatebox\number#1\endcsname
+ \tabl_tabulate_initialize_box_yes
+ \else
+ \tabl_tabulate_initialize_box_nop#1%
+ \fi}
+
+\def\tabl_tabulate_initialize_box_yes {\global \setbox\lastnamedcs\emptybox}
+\def\tabl_tabulate_initialize_box_nop#1{\expandafter\newbox\csname\??tabulatebox\number#1\endcsname}
+
+\tabl_tabulate_initialize_boxes{16} % not really needed
+
+\let\initializetablebox \tabl_tabulate_initialize_box % used elsewhere, will change
+\let\initializetableboxes\tabl_tabulate_initialize_boxes % used elsewhere, will change
+\let\tablebox \b_tabl_tabulate_current
+
+% 0 = NC column next EQ equal column
+% 1 = RC column raw RQ equal column raw
+% 2 = HC column hook HQ equal column hook
+
+% handy helper
+
+\def\tabulatenoalign % public ?
+ {\noalign
+ \bgroup
+ \let\noalign\relax
+ \let\tabulatenoalign\relax
+ \let\next=}
+
+\def\starttabulatenoalign % public ?
+ {\tabulatenoalign\bgroup}
+
+\let\stoptabulatenoalign\egroup
+
+% [|lg{.}|] => \NG 12.34 \NC
+
+\def\tabl_tabulate_nobreak_inject_tracer
+ {\red % maybe use the fast color switcher here
+ \hrule\s!height.5\linewidth\s!depth.5\linewidth
+ \par
+ \kern-\linewidth
+ \tabl_tabulate_break_no}
+
+\installtextracker
+ {tables.tabulate.breaks}
+ {\let\tabl_tabulate_break_no_tracer\tabl_tabulate_nobreak_inject_tracer}
+ {\let\tabl_tabulate_break_no_tracer\donothing}
+
+\let\tabl_tabulate_break_no_tracer\donothing
+
+\def\tabl_tabulate_nobreak_inject_indeed
+ {\tabl_tabulate_break_no
+ \tabl_tabulate_break_no_tracer}
+
+\def\tabl_tabulate_nobreak_inject
+ {\tabulatenoalign{\tabl_tabulate_nobreak_inject_indeed}}
+
+\unexpanded\def\tabl_tabulate_hook_check
+ {\ifnum\c_tabl_tabulate_type<\plustwo
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
+ \else
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \fi}
+
+\unexpanded\def\tabl_tabulate_setups_check
+ {\begincsname\??tabulatesetup\the\c_tabl_tabulate_column\endcsname}
+
+\unexpanded\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook}
+\unexpanded\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi}
+
+\unexpanded\def\tabl_tabulate_shaped_par_begin
+ {\dowithnextboxcs\tabl_tabulate_shaped_par_finish\vbox\bgroup}
+
+\def\tabl_tabulate_shaped_par_finish
+ {\clf_doreshapeframedbox\nextbox\relax
+ \ifvmode\unvbox\else\box\fi\nextbox}
+
+\let\tabl_tabulate_shaped_par_end\egroup
+
+\ifdefined\dotagtabulatecell \else \let\dotagtabulatecell \relax \fi
+\ifdefined\dotagtabulatesignal \else \let\dotagtabulatesignal\relax \fi
+
+\unexpanded\def\tabl_tabulate_check_local_color_first#1#2%
+ {\relax}
+
+\unexpanded\def\tabl_tabulate_check_local_color_second#1#2%
+ {\relax
+ \ifx\m_tabl_tabulate_color_local\empty
+ \xdef\m_tabl_tabulate_color{#1}%
+ \else
+ \glet\m_tabl_tabulate_color\m_tabl_tabulate_color_local
+ \glet\m_tabl_tabulate_color_local\empty
+ \fi
+ \ifcase\c_tabl_tabulate_localcolorspan
+ \global\c_tabl_tabulate_colorspan#2\relax
+ \else
+ \global\c_tabl_tabulate_colorspan\c_tabl_tabulate_localcolorspan
+ \global\c_tabl_tabulate_localcolorspan\zerocount
+ \fi}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_thickness#1%
+ {\relax
+ \ifcase\d_tabl_tabulate_vrulethickness_local
+ \global\d_tabl_tabulate_vrulethickness#1\relax
+ \else
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_local
+ \global\d_tabl_tabulate_vrulethickness_local\zeropoint
+ \fi}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_color_first#1%
+ {\relax}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_color_second#1%
+ {\relax
+ \ifx\m_tabl_tabulate_vrule_color_local\empty
+ \xdef\m_tabl_tabulate_vrule_color{#1}%
+ \else
+ \glet\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local
+ \glet\m_tabl_tabulate_vrule_color_local\empty
+ \fi}
+
+\let\tabl_tabulate_check_local_color \gobbletwoarguments
+\let\tabl_tabulate_check_local_vrule_color\gobbleoneargument
+
+\appendtoks
+ \let\tabl_tabulate_check_local_color \tabl_tabulate_check_local_color_first
+ \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_check_local_color \tabl_tabulate_check_local_color_second
+ \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_second
+\to \t_tabl_tabulate_initializers_second
+
+% \unexpanded % we can expand this one
+\def\tabl_tabulate_inject_pre_skip#1%
+ {\ifdim#1>\zeropoint
+ \kern#1\relax % was \hskip
+ \orelse\ifnum\c_tabl_tabulate_column=\zerocount
+ \ifconditional\c_tabl_tabulate_autorulespacing
+ \ifcase\c_tabl_tabulate_has_rule_spec_first\else
+ \kern\s_tabl_tabulate_first\relax % was \hskip
+ \fi
+ \fi
+ \fi}
+
+% \unexpanded % we can expand this one
+\def\tabl_tabulate_inject_post_skip#1%
+ {\ifdim#1>\zeropoint
+ \kern#1\relax % was \hskip
+ \orelse\ifnum\c_tabl_tabulate_columns=\c_tabl_tabulate_nofcolumns
+ \ifconditional\c_tabl_tabulate_autorulespacing
+ \ifcase\c_tabl_tabulate_has_rule_spec_last\else
+ \kern\s_tabl_tabulate_last\relax % was \hskip
+ \fi
+ \fi
+ \fi}
+
+\let\tabl_tabulate_hook_b\donothing
+\let\tabl_tabulate_hook_e\donothing
+
+\let\tabl_tabulate_hook_g\donothing
+
+\def\tabl_tabulate_set_preamble_step#1#2% only makes sense for many tabulates
+ {\etoksapp\t_tabl_tabulate_preamble{%
+ \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+ \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+ \tabl_tabulate_check_local_color\constantemptyargument\m_tabl_tabulate_color\constantnumberargument\c_tabl_tabulate_colorspan
+ \tabl_tabulate_color_side_right
+ \aligntab
+ \tabl_tabulate_column_vrule_inject
+ \tabl_tabulate_color_side_left
+ \tabl_tabulate_inject_pre_skip{\the\dimexpr\s_tabl_tabulate_pre}% get rid of plus
+ \alignmark\alignmark
+ \aligntab
+ \tabl_tabulate_color_side_both
+ \global\c_tabl_tabulate_colorspan\zerocount
+ \global\c_tabl_tabulate_column\constantnumber\c_tabl_tabulate_columns
+ \tabl_tabulate_hook_g
+ \tabl_tabulate_setups_check % unexpandable
+ \tabl_tabulate_hook_check % unexpandable
+ \ifzeropt\d_tabl_tabulate_width
+ \ifcase\c_tabl_tabulate_modus\else
+ \settrue\c_tabl_tabulate_automode
+ \fi
+ \else
+ \ifcase\c_tabl_tabulate_modus
+ \hbox to
+ \else
+ \hsize
+ \fi
+ \the\d_tabl_tabulate_width
+ \fi
+ \bgroup
+ \tabl_tabulate_bbskip
+ \bgroup % we cannot combine the if because a cell may have only one ##
+ \tabl_tabulate_hook_b
+ \c_tabl_tabulate_align\constantnumber\c_tabl_tabulate_align % needed in tag passing
+ \ifx\m_tabl_tabulate_alignment\empty \else
+ \spac_align_use_now{\m_tabl_tabulate_alignment}%
+ \fi
+ \noexpand\dostarttagged\noexpand\t!tabulatecell\noexpand\empty
+ \noexpand\dotagtabulatecell
+ \noexpand#1%
+ \ifconditional\c_tabl_tabulate_reshape
+ \tabl_tabulate_shaped_par_begin
+ \fi
+ \dotagtabulatesignal % empty cells .. todo (can be removed as soon as build)
+ \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+ \the\t_tabl_tabulate_bmath % maybe later? can interfere with char 0
+ \the\t_tabl_tabulate_font
+ \the\t_tabl_tabulate_settings
+ \the\t_tabl_tabulate_before
+ \ifx\m_tabl_tabulate_text_color\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\dofastcoloractivation
+ \fi\m_tabl_tabulate_text_color
+ \noexpand\fi
+ % grouping needs to be outside macros (or expandable), nice test
+ % example \NC \string \aligntab \NC which will fail otherwise (mk)
+ \bgroup
+ \tabl_tabulate_entry_before
+ \alignmark\alignmark
+ \tabl_tabulate_entry_after
+ \egroup
+ \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+ \the\t_tabl_tabulate_after
+ \the\t_tabl_tabulate_emath
+ \noexpand\fi
+ \ifconditional\c_tabl_tabulate_reshape
+ \tabl_tabulate_shaped_par_end
+ \fi
+ \noexpand#2%
+ \tabl_tabulate_hook_e
+ \egroup
+ \egroup
+ \aligntab
+ \noexpand\dostoptagged
+ \tabl_tabulate_inject_post_skip{\the\dimexpr\s_tabl_tabulate_post}% get rid of plus
+ \alignmark\alignmark
+ }%
+ \toksapp\t_tabl_tabulate_dummy{\NC}%
+ \s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\relax
+ \ifnum\c_tabl_tabulate_columns<\numexpr\c_tabl_tabulate_nofcolumns-\plusone\relax
+ \s_tabl_tabulate_post\s_tabl_tabulate_pre
+ \else
+ \s_tabl_tabulate_post\zeropoint
+ \fi
+ %\let\gettabulateexit\dogettabulateexit % still needed ?
+ \d_tabl_tabulate_width\zeropoint}
+
+\unexpanded\def\installtabulatepreambleoption#1#2%
+ {\setvalue{\??tabulatepreamble\string#1}{#2}}%
+
+\installtabulatepreambleoption{x}{\c_tabl_tabulate_align\zerocount
+ \tabl_tabulate_set_preamble} % internal
+\installtabulatepreambleoption{l}{\c_tabl_tabulate_align\plusone
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{r}{\c_tabl_tabulate_align\plustwo
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{c}{\c_tabl_tabulate_align\plusthree
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{p}{\tabl_tabulate_set_paragraph}
+\installtabulatepreambleoption{s}{\tabl_tabulate_set_setups}
+\installtabulatepreambleoption{w}{\tabl_tabulate_set_width}
+\installtabulatepreambleoption{f}{\tabl_tabulate_set_font}
+\installtabulatepreambleoption{B}{\t_tabl_tabulate_font{\bf}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{I}{\t_tabl_tabulate_font{\it}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{S}{\t_tabl_tabulate_font{\sl}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{T}{\t_tabl_tabulate_font{\tt}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{R}{\t_tabl_tabulate_font{\rm}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{m}{\t_tabl_tabulate_bmath{\normalstartimath}%
+ \t_tabl_tabulate_emath{\normalstopimath}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{M}{\t_tabl_tabulate_bmath{\normalstartimath\displaystyle}%
+ \t_tabl_tabulate_emath{\normalstopimath}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{h}{\tabl_tabulate_set_hook}
+\installtabulatepreambleoption{b}{\tabl_tabulate_set_before}
+\installtabulatepreambleoption{a}{\tabl_tabulate_set_after}
+\installtabulatepreambleoption{i}{\tabl_tabulate_set_preskip}
+\installtabulatepreambleoption{j}{\tabl_tabulate_set_posskip}
+\installtabulatepreambleoption{k}{\tabl_tabulate_set_preposskip}
+\installtabulatepreambleoption{e}{\toksapp\t_tabl_tabulate_settings{\global\settrue\c_tabl_tabulate_equal}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{g}{\tabl_tabulate_set_align}
+\installtabulatepreambleoption{.}{\tabl_tabulate_set_align.}
+\installtabulatepreambleoption{,}{\tabl_tabulate_set_align,}
+\installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span}
+\installtabulatepreambleoption{d}{\toksapp\t_tabl_tabulate_settings{\fixedspaces}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{A}{\tabl_tabulate_set_alignment}
+
+%D We no longer deal with \type {~} here but map it onto \type {d} instead. Of
+%D course we could prefix a key with \type {\meaning} instead, which works ok (and
+%D is needed in order to pseudo expand \type {\next}, but is ugly at the same time.
+%D The type {d} stands for digitspace.
+
+%D \starttyping
+%D \installtabulatepreambleoption{~}{...} % see 'd'
+%D \stoptyping
+%D
+%D Also, as there is always a key, we no longer do some after assigment or future
+%D let but just pick up the key.
+
+% \installtabulatepreambleoption \s!unknown %
+% {\writestatus{tabulate}{unknown preamble key [\normalmeaning\next]}%
+% \tabl_tabulate_set_preamble}
+%
+% \def\tabl_tabulate_set_preamble
+% {\afterassignment\dosettabulatepreamble\let\next=}
+%
+% \def\dosettabulatepreamble
+% {\ifx\next\relax \else
+% \csname\??tabulatepreamble
+% \ifcsname\??tabulatepreamble\next\endcsname\next\else\s!unknown\fi
+% \expandafter\endcsname
+% \fi}
+
+\installtabulatepreambleoption\relax
+ {} % finished
+
+\def\tabl_tabulate_set_preamble#1%
+ {\ifcsname\??tabulatepreamble\string#1\endcsname
+ %\expandafter\tabl_tabulate_set_preamble_yes
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\tabl_tabulate_set_preamble_nop
+ \fi{#1}}
+
+\def\tabl_tabulate_set_preamble_yes#1%
+ {\csname\??tabulatepreamble\string#1\expandafter\endcsname}
+
+\def\tabl_tabulate_set_preamble_nop#1%
+ {\writestatus{tabulate}{unknown preamble key: #1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_preskip#1%
+ {\doifelsenumber{#1}%
+ {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }%
+ {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
+
+\def\tabl_tabulate_set_posskip#1%
+ {\doifelsenumber{#1}%
+ {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }%
+ {\s_tabl_tabulate_post.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
+
+\def\tabl_tabulate_set_preposskip#1%
+ {\doifelsenumber{#1}%
+ {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble }%
+ {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble#1}}
+
+\def\tabl_tabulate_set_setups#1%
+ {\setvalue{\??tabulatesetup\the\c_tabl_tabulate_columns}{\setups[#1]}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_hook#1%
+ {\setvalue{\??tabulatehook\the\c_tabl_tabulate_columns}{#1}%
+ \tabl_tabulate_set_preamble}
+
+% begin of character align plugin
+
+\newconditional\c_tabl_auto_align_mode % reset later
+
+\def\tabl_tabulate_hook_g % partly expanded
+ {\ifconditional\c_tabl_auto_align_mode
+ \signalcharacteralign\c_tabl_tabulate_column{\c_tabl_tabulate_noflines+\plusone}%
+ \typo_charalign_adapt_font
+ \fi}
+
+\def\tabl_tabulate_set_align#1%
+ {\global\settrue\c_tabl_auto_align_mode
+ \setcharacteralign\c_tabl_tabulate_columns{#1}%
+ \tabl_tabulate_set_preamble}
+
+% end of character align plugin
+
+\def\tabl_tabulate_set_before#1%
+ {\t_tabl_tabulate_before{#1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_after#1%
+ {\t_tabl_tabulate_after{#1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_font#1%
+ {\t_tabl_tabulate_font{#1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_pickup_width
+ {\doifelsenextparenthesis\tabl_tabulate_set_width_indeed\tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_width
+ {\setfalse\c_tabl_tabulate_pwidth_set
+ \c_tabl_tabulate_modus\zerocount
+ \tabl_tabulate_pickup_width}
+
+\def\tabl_tabulate_set_alignment#1%
+ {\edef\m_tabl_tabulate_alignment{#1}%
+ \spac_align_use_later\m_tabl_tabulate_alignment
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_paragraph
+ {\doifelsenextparenthesis
+ {\c_tabl_tabulate_modus\plusone
+ \settrue\c_tabl_tabulate_pwidth_set
+ \tabl_tabulate_pickup_width}
+ {\c_tabl_tabulate_modus\plustwo
+ \setfalse\c_tabl_tabulate_pwidth_set
+ \tabl_tabulate_set_preamble}}
+
+% \startbuffer
+% \toplinebox{\framed[width=3cm,height=2cm]{tufte}}
+% \stopbuffer
+% \starttabulate[|p(fixed)|p|]
+% \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
+% \stoptabulate
+% \starttabulate[|p(fit)|p|]
+% \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
+% \stoptabulate
+
+\def\tabl_tabulate_set_width_indeed(#1)%
+ {\processallactionsinset % can be made faster
+ [#1]%
+ [ \v!fit=>\c_tabl_tabulate_modus\plusthree,
+ \v!fixed=>\c_tabl_tabulate_modus\plusthree
+ \settrue\c_tabl_tabulate_nopbreak,
+ \v!auto=>\c_tabl_tabulate_modus\plusthree
+ \settrue\c_tabl_tabulate_reshape,
+ \s!unknown=>\d_tabl_tabulate_width#1\relax]%
+ \ifconditional\c_tabl_tabulate_pwidth_set
+ \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth
+ \fi
+ \tabl_tabulate_set_preamble}
+
+% faster but seldom used
+%
+% \installcorenamespace{tabulatewidth}
+%
+% \setvalue{\??tabulatewidth\v!fit }{\c_tabl_tabulate_modus\plusthree}
+% \setvalue{\??tabulatewidth\v!fixed}{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_nopbreak}
+% \setvalue{\??tabulatewidth\v!auto }{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_reshape}
+%
+% \def\tabl_tabulate_set_width_step#1%
+% {\ifcsname\??tabulatewidth#1\endcsname
+% \lastnamedcs
+% \else
+% \d_tabl_tabulate_width#1\relax
+% \fi}
+%
+% \def\tabl_tabulate_set_width_indeed(#1)%
+% {\rawprocesscommacommand[#1]\tabl_tabulate_set_width_step
+% \ifconditional\c_tabl_tabulate_pwidth_set
+% \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth
+% \fi
+% \tabl_tabulate_set_preamble}
+%
+\def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi}
+\def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi}
+\def\tabl_tabulate_set_raggedleft {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft \fi}
+\def\tabl_tabulate_set_notragged {\ifnum\c_tabl_tabulate_type=\plusone \else\notragged \fi}
+\def\tabl_tabulate_set_hss {\ifnum\c_tabl_tabulate_type=\plusone \else\hss \fi} % never change this to a fill
+
+\def\tabl_tabulate_bskip_raggedright {\tabl_tabulate_bskip\tabl_tabulate_set_raggedright }
+\def\tabl_tabulate_bskip_raggedleft {\tabl_tabulate_bskip\tabl_tabulate_set_raggedleft }
+\def\tabl_tabulate_bskip_raggedcenter{\tabl_tabulate_bskip\tabl_tabulate_set_raggedcenter}
+
+\def\tabl_tabulate_set_width_normal
+ {\ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\empty \tabl_tabulate_set_hss \or
+ \tabl_tabulate_set_preamble_step\empty \tabl_tabulate_set_hss \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\empty \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\tabl_tabulate_set_hss \fi}
+
+\def\tabl_tabulate_set_width_fixed
+ {\ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
+
+\def\tabl_tabulate_set_width_auto
+ {\global\advance\c_tabl_tabulate_nofauto\plusone
+ \ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
+
+\def\tabl_tabulate_set_width_simple
+ {\tabl_tabulate_set_preamble_step\tabl_tabulate_xbskip\tabl_tabulate_xeskip}
+
+% \def\tabl_tabulate_set_color_span#1#2%
+% {\xdef\m_tabl_tabulate_color{#2}%
+% \global\c_tabl_tabulate_colorspan\if#1L\plusone\else\if#1M\plustwo\else\if#1R\plusthree\else\zerocount\fi\fi\fi\relax
+% \tabl_tabulate_set_preamble}
+
+\installcorenamespace{tabulatecolorspec}
+
+\setvalue{\??tabulatecolorspec C}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\zerocount}
+\setvalue{\??tabulatecolorspec L}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\plusone }
+\setvalue{\??tabulatecolorspec M}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\plustwo }
+\setvalue{\??tabulatecolorspec R}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\plusthree}
+\setvalue{\??tabulatecolorspec T}#1{\xdef\m_tabl_tabulate_text_color{#1}}
+
+\def\tabl_tabulate_set_color_span#1#2%
+ {\csname\??tabulatecolorspec#1\endcsname{#2}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_vrule_command#1%
+ {\doifelsenumber{#1}
+ {\global\d_tabl_tabulate_vrulethickness#1\d_tabl_tabulate_vrulethickness_default}
+ {\xdef\m_tabl_tabulate_vrule_color{#1}}}
+
+\def\tabl_tabulate_set_entry#1#2% rulespec template
+ {\c_tabl_tabulate_align\v_tabl_tabulate_align
+ \c_tabl_tabulate_modus\zerocount
+ \setfalse\c_tabl_tabulate_pwidth_set
+ \setfalse\c_tabl_tabulate_reshape
+ \t_tabl_tabulate_before\emptytoks
+ \t_tabl_tabulate_after\emptytoks
+ \t_tabl_tabulate_bmath\emptytoks
+ \t_tabl_tabulate_emath\emptytoks
+ \t_tabl_tabulate_font\emptytoks
+ \t_tabl_tabulate_settings\emptytoks
+ \glet\m_tabl_tabulate_alignment\empty
+ \glet\m_tabl_tabulate_color\empty
+ \glet\m_tabl_tabulate_text_color\empty
+ \glet\m_tabl_tabulate_vrule_color\empty
+ \global\c_tabl_tabulate_colorspan\zerocount
+ \global\setfalse\c_tabl_auto_align_mode
+ \global\advance\c_tabl_tabulate_columns\plusone
+ \expandafter\let\csname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname\donothing % here ?
+ \edef\currenttabulationtrulespec{#1}%
+ \ifx\currenttabulationtrulespec\empty
+ \global\d_tabl_tabulate_vrulethickness\zeropoint
+ \else
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+ \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
+ \fi
+ \tabl_tabulate_set_preamble#2\relax\relax % permits i without n
+ \ifcase\c_tabl_tabulate_modus\relax
+ \tabl_tabulate_set_width_normal
+ \or % fixed width
+ \tabl_tabulate_set_width_fixed
+ \or % auto width
+ \tabl_tabulate_set_width_auto
+ \or % simple
+ \tabl_tabulate_set_width_simple
+ \fi}
+
+\def\tabl_tabulate_set_last_entry#1% rulespec
+ {\glet\m_tabl_tabulate_color\empty
+ \glet\m_tabl_tabulate_vrule_color\empty
+ \edef\currenttabulationtrulespec{#1}%
+ \ifx\currenttabulationtrulespec\empty
+ \global\d_tabl_tabulate_vrulethickness\zeropoint
+ \else
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+ \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
+ \fi
+ \etoksapp\t_tabl_tabulate_preamble{%
+ \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+ \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+ \tabl_tabulate_column_vrule_inject}}
+
+\let\settabulateentry \tabl_tabulate_set_entry % used at the lua end
+\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end
+
+\def\tabl_tabulate_normalize_splitline
+ {\ifcase\c_tabl_tabulate_splitlinemode
+ % nothing
+ \or
+ \ht\b_tabl_tabulate\strutht
+ \dp\b_tabl_tabulate\strutdp
+ \or
+ \ifdim\ht\b_tabl_tabulate<\strutht
+ \ht\b_tabl_tabulate\strutht
+ \fi
+ \ifdim\dp\b_tabl_tabulate<\strutdp
+ \dp\b_tabl_tabulate\strutdp
+ \fi
+ \fi}
+
+\def\tabl_tabulate_whitespace
+ {\ifdim\d_tabl_tabulate_splitoff_betweenskip>\zeropoint
+ \vskip\d_tabl_tabulate_splitoff_betweenskip
+ \global\d_tabl_tabulate_splitoff_betweenskip\zeropoint
+ \fi}
+
+\def\tabl_tabulate_check_whitespace
+ {\setbox\scratchbox\vpack
+ {\splitdiscards
+ \unskip
+ \ifdim\lastskip>\d_tabl_tabulate_splitoff_betweenskip
+ \global\d_tabl_tabulate_splitoff_betweenskip\lastskip
+ \fi}}
+
+\installtexdirective
+ {tabulate.linenumbers}
+ {\def\tabl_tabulate_check_linenumbers{\page_postprocessors_linenumbers_deepbox\b_tabl_tabulate}}
+ {\let\tabl_tabulate_check_linenumbers\relax}
+
+\let\tabl_tabulate_check_linenumbers\relax
+
+\def\tabl_tabulate_splitoff_box
+ {\dontcomplain
+ \global\setbox\b_tabl_tabulate\vsplit\b_tabl_tabulate_current\c_tabl_tabulate_column to \lineheight % % % global ? % % %
+ \setbox\b_tabl_tabulate\vbox
+ {\unvbox\b_tabl_tabulate}%
+ \ifconditional\c_tabl_tabulate_splitoff_whitespace
+ \tabl_tabulate_check_whitespace
+ \fi
+ \tabl_tabulate_color_repeat % needs to end up in a cell
+ \setbox\b_tabl_tabulate\hpack to \wd\b_tabl_tabulate
+ {\hss\tabl_tabulate_hook_yes{\box\b_tabl_tabulate}\hss}%
+ \tabl_tabulate_normalize_splitline
+ \tabl_tabulate_check_linenumbers
+ \box\b_tabl_tabulate}
+
+\unexpanded\def\tabl_tabulate_hook_nop
+ {}
+
+\let\tabl_tabulate_hook\tabl_tabulate_hook_nop
+
+\def\tabl_tabulate_hook_yes{\begincsname\??tabulatehook\the\c_tabl_tabulate_column\endcsname}
+
+\def\tabl_tabulate_pheight_reset
+ {\global\c_tabl_tabulate_plines_min\plusone
+ \ifdim\d_tabl_tabulate_height_p_max>\zeropoint
+ \getnoflines\d_tabl_tabulate_height_p_max
+ \global\c_tabl_tabulate_plines_max\noflines
+ \else
+ \global\c_tabl_tabulate_plines_max\zerocount
+ \fi
+ \global\d_tabl_tabulate_height_p_max\zeropoint}
+
+\def\tabl_tabulate_pheight_set
+ {\scratchdimen\ht\b_tabl_tabulate_current\c_tabl_tabulate_column\relax
+ \ifdim\scratchdimen>\d_tabl_tabulate_height_p_max
+ \global\d_tabl_tabulate_height_p_max\scratchdimen
+ \fi}
+
+\def\tabl_tabulate_pbreak_inject
+ {\ifconditional\c_tabl_tabulate_handlepbreak
+ \ifconditional\c_tabl_tabulate_nopbreak
+ \tabl_tabulate_nobreak_inject
+ \orelse\ifnum\c_tabl_tabulate_plines_max>\plusone
+ \ifnum\c_tabl_tabulate_plines_min=\plusone
+ \tabl_tabulate_nobreak_inject
+ \fi
+ \global\advance\c_tabl_tabulate_plines_min\plusone
+ \ifnum\c_tabl_tabulate_plines_min=\c_tabl_tabulate_plines_max\relax
+ \tabl_tabulate_nobreak_inject
+ \fi
+ \fi
+ \fi}
+
+\def\tabl_tabulate_pbreak_check
+ {\starttabulatenoalign
+ \tabl_tabulate_pbreak_inject
+ \ifconditional\c_tabl_tabulate_splitoff_whitespace
+ \tabl_tabulate_whitespace
+ \fi
+ \stoptabulatenoalign}
+
+%D \startbuffer
+%D \starttabulate[|c|p|p|]
+%D \NC \bf Alpha \NC \bf Beta \NC \bf Gamma \NC\NR
+%D \NC 1 \NC right indeed \NC definitely wrong \NC\NR
+%D \NC 2 \NC \thinrules[n=3] \NC \thinrules[n=3] \NC\NR
+%D \NC 3 \NC oh yes \NC simply no \NC\NR
+%D \NC 4 \NC very true \NC as false as can be \NC\NR
+%D \NC 5 \NC \thinrules[n=5] \NC \thinrules[n=5] \NC\NR
+%D \NC 6 \NC \thinrules[n=3] \NC \thinrules[n=4] \NC\NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer {\tracetabulatetrue\getbuffer}
+%D
+%D \startbuffer
+%D \starttabulate[|c|p|p|]
+%D \NC \bf Alpha \NC \bf Beta \NC \bf Gamma \NC\NR
+%D \NC 1 \NC right indeed \NC definitely wrong \NC\NR
+%D \NC 2 \NC oh yes \NC simply no \NC\NR
+%D \NC 3 \NC very true \NC as false as can be \NC\NR
+%D \NC 4 \NC the whole truth \NC but the truth \NC\NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer {\tracetabulatetrue\getbuffer}
+
+%D Because we want to be compatible we use an indirect way to implement the
+%D definers. The next examples demonstrate the difference:
+%D
+%D \starttyping
+%D \definetabulate[test][|l|c|r|]
+%D \definetabulate[test][two][|r|c|l|]
+%D
+%D \definetabulation[more][format={|l|c|r|}]
+%D \definetabulation[more:two][format={|r|c|l|}]
+%D
+%D \starttest
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stoptest
+%D
+%D \starttest[two]
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stoptest
+%D \startmore
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stopmore
+%D
+%D \startmore[two]
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stopmore
+%D \stoptyping
+
+\installcorenamespace {tabulation}
+
+\installcommandhandler \??tabulation {tabulation} \??tabulation
+
+\setuptabulation
+ [\c!unit=1em,
+ EQ={:},
+ \c!format={|l|p|},
+ \c!frame=\v!off,
+ %\c!bodyfont=,
+ \c!rule=\v!normal,
+ %\c!rulecolor=,
+ \c!rulethickness=\linewidth,
+ %\c!inner=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance={\v!depth,\v!medium},
+ \c!align=\v!normal,
+ \c!margin=\!!zeropoint,
+ \c!split=\v!auto,
+ \c!header=\v!yes,
+ %\c!title=,
+ \c!indenting=\v!no]
+
+\unexpanded\def\definetabulate
+ {\dotripleempty\tabl_tabulate_define}
+
+\def\tabl_tabulate_define[#1][#2][#3]%
+ {\ifthirdargument
+ % [tag] [sub] [template]
+ \ifcsname\namedtabulationhash{#1}\s!check\endcsname \else
+ \definetabulation[#1][\c!format={#3},\s!check=]%
+ \fi
+ \definetabulation[#1:#2][#1][\c!format={#3},\s!check=]%
+ \orelse\ifsecondargument
+ % [tag] [template]
+ \definetabulation[#1][\c!format={#2},\s!check=]%
+ \else
+ % [tag]
+ \definetabulation[#1][\c!format={|l|p|},\s!check=]%
+ \fi}
+
+\unexpanded\def\setuptabulate
+ {\dotripleempty\tabl_tabulate_setup}
+
+\def\tabl_tabulate_setup[#1][#2][#3]%
+ {\ifthirdargument
+ % [tag] [sub] [settings]
+ \setuptabulation[#1:#2][#3]%
+ \orelse\ifsecondargument
+ % [tag] [settings]
+ \setuptabulation[#1][#2]%
+ \else
+ % [tag]
+ \setuptabulation[#1]%
+ \fi}
+
+\appendtoks
+ \setuevalue{\e!start\currenttabulation}{\tabl_start_defined[\currenttabulation]}%
+ \letvalue{\e!stop\currenttabulation}\relax
+ \letvalue{\??tabulatehead\currenttabulation}\empty
+ \letvalue{\??tabulatefoot\currenttabulation}\empty
+\to \everydefinetabulation
+
+\let\tabulateparameter\tabulationparameter % will stay for a while
+\def\currenttabulate {\currenttabulation} % will stay for a while
+
+% Here begins the implementation.
+
+\let\tabl_tabulate_insert_head\empty
+\let\tabl_tabulate_insert_body\empty
+\let\tabl_tabulate_insert_foot\empty
+
+\def\tabl_tabulate_insert_head_content
+ {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ \begincsname\??tabulatehead\currenttabulation\endcsname
+ \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+
+\def\tabl_tabulate_insert_foot_content
+ {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ \begincsname\??tabulatefoot\currenttabulation\endcsname
+ \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+
+\def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header
+ {\ifcsname\??tabulatehead\currenttabulation\endcsname
+ %\expandafter\ifx\csname\??tabulatehead\currenttabulation\endcsname\empty
+ \expandafter\ifx\lastnamedcs\empty
+ \let\tabl_tabulate_insert_head\empty
+ \else
+ \let\tabl_tabulate_insert_head\tabl_tabulate_insert_head_content
+ \fi
+ \else
+ \let\tabl_tabulate_insert_head\empty
+ \fi
+ \ifcsname\??tabulatefoot\currenttabulation\endcsname
+ \expandafter\ifx\csname\??tabulatefoot\currenttabulation\endcsname\empty
+ %\expandafter\ifx\lastnamedcs\empty
+ \let\tabl_tabulate_insert_foot\empty
+ \else
+ \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_foot_content
+ \fi
+ \else
+ \let\tabl_tabulate_insert_foot\empty
+ \fi}
+
+\def\tabl_tabulate_insert_content
+ {\tabl_tabulate_insert_head
+ \ifcase\c_tabl_tabulate_repeathead \else
+ \tabulatenoalign{\penalty\zerocount}% added 7/5/2014 WS mail
+ \fi
+ \tabl_tabulate_insert_body
+ \tabl_tabulate_insert_foot
+ \tabl_tabulate_remove_funny_line}
+
+\def\tabl_tabulate_remove_funny_line
+ {\ifhmode
+ \strut\crcr
+ \tabulatenoalign{\kern-\lineheight}%
+ \fi}
+
+% todo: make footer synonym to tail
+
+\setuvalue{\e!start\v!tabulatehead}{\doifelsenextoptionalcs\tabl_tabulate_start_head_yes\tabl_tabulate_start_head_nop}
+\setuvalue{\e!start\v!tabulatetail}{\doifelsenextoptionalcs\tabl_tabulate_start_foot_yes\tabl_tabulate_start_foot_nop}
+
+\let\m_tabl_tabulate_data\empty
+
+\def\tabl_tabulate_start_head_yes[#1]%
+ {\processcontent{\e!stop\v!tabulatehead}\m_tabl_tabulate_data{\letvalue{\??tabulatehead#1}\m_tabl_tabulate_data}}
+
+\def\tabl_tabulate_start_foot_yes[#1]%
+ {\processcontent{\e!stop\v!tabulatetail}\m_tabl_tabulate_data{\letvalue{\??tabulatefoot#1}\m_tabl_tabulate_data}}
+
+\def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[\v!tabulate]}
+\def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[\v!tabulate]}
+
+\unexpanded\def\tabl_start_defined[#1]%
+ {\bgroup
+ \edef\currenttabulationparent{#1}%
+ \let\currenttabulation\currenttabulationparent
+ \edef\p_format{\tabulationparameter\c!format}%
+ \ifx\p_format\v!none
+ % this is special case: we need to define the generic english
+ % \starttabulate in other interfaces as well
+ \expandafter\dodoubleempty \expandafter\tabl_start_regular
+ \else
+ \expandafter\dodoubleargument\expandafter\tabl_start_defined_indeed
+ \fi}
+
+\def\tabl_start_defined_indeed
+ {\iffirstargument
+ \ifsecondargument
+ \doubleexpandafter\tabl_start_defined_two
+ \else
+ \doubleexpandafter\tabl_start_defined_one
+ \fi
+ \else
+ \singleexpandafter\tabl_start_defined_zero
+ \fi}
+
+\def\tabl_start_defined_one[#1][#2]%
+ {\ifcondition\validassignment{#1}%
+ \setuptabulation[\currenttabulation][#1]%
+ \else
+ \edef\currenttabulation{\currenttabulation:#1}%
+ \fi
+ \tabl_tabulate_start_building}
+
+\def\tabl_start_defined_two[#1][#2]%
+ {\edef\currenttabulation{\currenttabulation:#1}%
+ \setuptabulation[\currenttabulation][#2]%
+ \tabl_tabulate_start_building}
+
+\def\tabl_start_defined_zero[#1][#2]%
+ {\tabl_tabulate_start_building}
+
+% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one
+
+\unexpanded\setuvalue{\e!start\v!tabulate}%
+ {\bgroup % whole thing
+ \let\currenttabulationparent\empty
+ \dodoubleempty\tabl_start_regular}
+
+\def\tabl_start_regular
+ {\let\currenttabulation\currenttabulationparent
+ \ifsecondargument
+ \expandafter\tabl_start_regular_two
+ \else
+ \expandafter\tabl_start_regular_one
+ \fi}
+
+\def\tabl_default_format{|l|p|}
+
+\def\tabl_start_regular_one[#1][#2]%
+ {\ifcondition\validassignment{#1}%
+ \lettabulationparameter\c!format\tabl_default_format
+ \setupcurrenttabulation[#1]%
+ \else
+ \def\p_format{#1}%
+ \ifx\p_format\empty
+ \def\p_format{|l|p|}%
+ \fi
+ \lettabulationparameter\c!format\p_format
+ \fi
+ \tabl_tabulate_start_building}
+
+\def\tabl_start_regular_two[#1][#2]%
+ {\def\p_format{#1}%
+ \ifx\p_format\empty
+ \let\p_format\tabl_default_format
+ \fi
+ \lettabulationparameter\c!format\p_format
+ \setupcurrenttabulation[#2]%
+ \tabl_tabulate_start_building}
+
+\letvalue{\e!stop\v!tabulate }\relax
+\letvalue{\e!stop\v!tabulatehead}\relax
+\letvalue{\e!stop\v!tabulatetail}\relax
+
+\unexpanded\def\tabl_tabulate_start_ignore
+ {\em Nested tabulate is not (yet) supported.\relax
+ \expandafter\gobbleuntil\csname\ifconditional\c_tabl_generic stoptabulate\else\e!stop\v!tabulate\fi\endcsname}
+
+\appendtoks
+ \letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one
+\to \everytabulate
+
+\setvalue{\??tabulatesplit\v!yes }{\settrue\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!repeat}{\settrue\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!no }{\setfalse\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!auto }{\ifinsidefloat\ifinsidesplitfloat\else\setfalse\c_tabl_tabulate_split\fi\fi}
+
+% todo: spacing around tabulate when bodyfont is set
+
+% \let\tabl_tabulate_inside_before \relax
+% \let\tabl_tabulate_inside_after \relax
+% \let\tabl_tabulate_inside_inbetween\relax
+%
+% \def\tabl_tabulate_outside_before
+% {\whitespace
+% \tabulationparameter\c!before}
+%
+% \def\tabl_tabulate_outside_after
+% {\tabulationparameter\c!after}
+
+% \showboxes
+%
+% \startcombination
+% {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
+% {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
+% \stopcombination
+%
+% \startcombination
+% {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {}
+% {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {}
+% \stopcombination
+%
+% \startcombination
+% {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
+% {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
+% \stopcombination
+
+\let\tabl_tabulate_inside_after \relax
+\let\tabl_tabulate_outside_after \relax
+\let\tabl_tabulate_inside_inbetween \relax
+\let\tabl_tabulate_outside_inbetween\relax
+
+\unexpanded\def\tabl_tabulate_inside_before
+ {\ifhmode\par\fi
+ \ifhmode
+ \ifinsidesplitfloat
+ \let\tabl_tabulate_inside_after\relax
+ \else
+ \vbox\bgroup
+ \let\tabl_tabulate_inside_after\egroup
+ \fi
+ \else
+ \let\tabl_tabulate_inside_after\relax
+ \fi}
+
+\unexpanded\def\tabl_tabulate_outside_before
+ {\ifhmode\par\fi
+ \ifhmode
+ \vbox\bgroup
+ \let\tabl_tabulate_outside_after \egroup
+ \let\tabl_tabulate_outside_inbetween\relax
+ \orelse\ifinner
+ \let\tabl_tabulate_outside_after \relax
+ \let\tabl_tabulate_outside_inbetween\relax
+ \else
+ \whitespace
+ \tabulationparameter\c!before
+ \relax
+ \let\tabl_tabulate_outside_after \tabl_tabulate_outside_after_indeed
+ \let\tabl_tabulate_outside_inbetween\tabl_tabulate_outside_inbetween_indeed
+ \fi}
+
+\def\tabl_tabulate_outside_after_indeed
+ {\tabulationparameter\c!after}
+
+\def\tabl_tabulate_outside_inbetween_indeed
+ {\doifempty{\tabulationparameter\c!after}
+ {\vskip\strutdp
+ \verticalstrut
+ \vskip-\struttotal}}
+
+\def\tabl_tabulate_inside_inbetween % needs checking
+ {\doifempty{\tabulationparameter\c!after}
+ {\vskip\strutdp
+ \verticalstrut
+ \vskip-\struttotal}}
+
+\unexpanded\def\tabl_tabulate_start_building
+ {\ifinsidefloat
+ \tabl_tabulate_inside_before
+ \else
+ \tabl_tabulate_outside_before
+ \fi
+ \bgroup % settings
+ %
+ \t_tabl_tabulate_preamble\emptytoks
+ \t_tabl_tabulate_dummy \emptytoks
+ %
+ \resetcharacteralign
+ %
+ \edef\p_distance {\tabulationparameter\c!distance}%
+ \edef\p_align {\tabulationparameter\c!align}%
+ \edef\p_line {\tabulationparameter\c!rule}%
+ \edef\p_rulecolor {\tabulationparameter\c!rulecolor}%
+ \edef\p_rulethickness{\tabulationparameter\c!rulethickness}%
+ \edef\p_bodyfont {\tabulationparameter\c!bodyfont}
+ \edef\p_indenting {\tabulationparameter\c!indenting}%
+ \edef\p_keeptogether {\tabulationparameter\c!keeptogether}%
+ \edef\p_blank {\tabulationparameter\c!blank}%
+ %
+ \ifx\p_keeptogether\v!no
+ \settrue \c_tabl_tabulate_tolerant_break
+ %\setfalse\c_tabl_tabulate_handlepbreak
+ \else
+ \setfalse\c_tabl_tabulate_tolerant_break
+ %\settrue \c_tabl_tabulate_handlepbreak
+ \fi
+ %
+ \settrue\c_tabl_tabulate_split
+ \begincsname\??tabulatesplit\tabulationparameter\c!split\endcsname
+ %
+ \let\m_tabl_tabulate_blank_default\p_blank
+ %
+ \d_tabl_tabulate_unit\tabulationparameter\c!unit
+ \d_tabl_tabulate_margin\tabulationparameter\c!margin
+ \let\m_tabl_tabulate_vrule_color_default\p_rulecolor
+ \let\m_tabl_tabulate_hrule_color_default\p_rulecolor
+ \d_tabl_tabulate_vrulethickness_default\p_rulethickness
+ \d_tabl_tabulate_hrulethickness_default\p_rulethickness
+ \ifx\p_bodyfont\empty\else
+ \switchtobodyfont[\p_bodyfont]%
+ \fi
+ \postponenotes % new, to be tested / will be configurable
+ \widowpenalty\zerocount % otherwise lines are not broken
+ \clubpenalty \zerocount % but overlap in funny ways
+ \the\everytabulate
+ \tabulationparameter\c!inner
+ \d_tabl_tabulate_indent\dimexpr\leftskip+\hangindent\ifx\p_indenting\v!yes+\parindent\fi\relax
+ \global\c_tabl_tabulate_column\zerocount
+ \processcontent
+ {\ifconditional\c_tabl_generic stoptabulate\else\e!stop\ifx\currenttabulationparent\empty\v!tabulate\else\currenttabulationparent\fi\fi}
+ \tabl_tabulate_insert_body
+ \tabl_tabulate_process}
+
+\def\tabulateEQ
+ {\ifconditional\c_tabl_tabulate_firstflushed\else
+ \dostarttaggedchained\t!ignore\empty\empty
+ \dostarttagged\t!ignore\empty
+ \tabulationparameter{EQ}%
+ \dostoptagged
+ \dostoptagged
+ \fi
+ \global\setfalse\c_tabl_tabulate_equal}
+
+% The next ones will be token registers
+
+\let\tabulatenormalpos\relax % hooks, todo
+\let\tabulateequalpos \relax % hooks, todo
+
+% color columns
+
+\let\m_tabl_tabulate_color_previous \empty
+\let\m_tabl_tabulate_color \empty
+\let\m_tabl_tabulate_text_color \empty
+\let\m_tabl_tabulate_color_local \empty
+\let\m_tabl_tabulate_vrule_color \empty
+\let\m_tabl_tabulate_vrule_color_local \empty
+\let\m_tabl_tabulate_vrule_color_default\empty % used local
+\let\m_tabl_tabulate_hrule_color_default\empty % used local
+\let\m_tabl_tabulate_blank_default \empty
+
+\appendtoks
+ \glet\m_tabl_tabulate_color_previous \empty
+ \glet\m_tabl_tabulate_color \empty
+ \glet\m_tabl_tabulate_text_color \empty
+ \glet\m_tabl_tabulate_color_local \empty
+ \glet\m_tabl_tabulate_vrule_color \empty
+ \glet\m_tabl_tabulate_vrule_color_local \empty
+ \global \d_tabl_tabulate_vrulethickness_local\zeropoint
+\to \t_tabl_tabulate_every_row
+
+\unexpanded\def\tabl_tabulate_color_side_right_second
+ {\ifx\m_tabl_tabulate_color_previous\empty \else
+ \tabl_tabulate_color_set\m_tabl_tabulate_color_previous
+ \glet\m_tabl_tabulate_color_previous\empty
+ \fi}
+
+\unexpanded\def\tabl_tabulate_color_side_left_second
+ {\ifx\m_tabl_tabulate_color\empty \else
+ \ifcase\c_tabl_tabulate_colorspan
+ \or
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \or
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_color_side_both_second
+ {\ifx\m_tabl_tabulate_color\empty \else
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \ifcase\c_tabl_tabulate_colorspan
+ %\glet\m_tabl_tabulate_color_previous\empty
+ \or
+ \glet\m_tabl_tabulate_color_previous\empty
+ \or
+ \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
+ \or
+ \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
+ \fi
+ \fi}
+
+\let\tabl_tabulate_color_side_right \relax
+\let\tabl_tabulate_color_side_left \relax
+\let\tabl_tabulate_color_side_both \relax
+
+\appendtoks
+ \let\tabl_tabulate_color_side_right\tabl_tabulate_color_side_right_second
+ \let\tabl_tabulate_color_side_left \tabl_tabulate_color_side_left_second
+ \let\tabl_tabulate_color_side_both \tabl_tabulate_color_side_both_second
+\to \t_tabl_tabulate_initializers_second
+
+\def\tabl_tabulate_set_color_column#1% overloaded
+ {\unskip
+ \doifelsefastoptionalcheck{\tabl_tabulate_set_color_column_yes#1}{\tabl_tabulate_set_color_column_nop#1}}
+
+\def\tabl_tabulate_set_color_column_nop
+ {\tabl_tabulate_column_normal\zerocount}
+
+\def\tabl_tabulate_set_color_column_yes#1[#2]%
+ {\xdef\m_tabl_tabulate_color_local{#2}%
+ \tabl_tabulate_column_normal\zerocount#1}
+
+% normal columns:
+
+\def\tabl_tabulate_column_normal#1#2%
+ {\unskip
+ \aligntab
+ \ifconditional\c_tabl_tabulate_equal\tabulateequalpos\else\tabulatenormalpos\fi
+ \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn\else
+ \tabl_tabulate_column_vrule_setup
+ \fi
+ \aligntab
+ \global\c_tabl_tabulate_kind#1%
+ \global\c_tabl_tabulate_type#2%
+ \aligntab}
+
+% equal columns
+
+\def\tabl_tabulate_column_equal#1#2%
+ {\unskip
+ \aligntab
+ \tabulateequalpos
+ \aligntab
+ \global\c_tabl_tabulate_kind#1%
+ \global\c_tabl_tabulate_type#2%
+ \aligntab}
+
+% ruled columns
+
+\def\tabl_tabulate_column_vruled_preset
+ {\glet\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default
+ \global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default}
+
+\def\tabl_tabulate_column_vruled#1#2%
+ {\unskip % 0-n
+ %\ifnum\c_tabl_tabulate_column=\plusone
+ % \global\c_tabl_tabulate_has_rule_spec_first\plusone
+ %\orelse\ifnum\c_tabl_tabulate_column=\c_tabl_tabulate_nofcolumns
+ % \global\c_tabl_tabulate_has_rule_spec_last\plusone
+ %\fi
+ \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn
+ \global\c_tabl_tabulate_max_vrulecolumn\c_tabl_tabulate_column
+ \fi
+ \doifelsefastoptionalcheck{\tabl_tabulate_column_vruled_yes#1#2}{\tabl_tabulate_column_vruled_nop#1#2}}
+
+\def\tabl_tabulate_column_vrule_setup
+ {\begincsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname}
+
+\def\tabl_tabulate_column_vruled_nop
+ {\expandafter\glet\csname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname\tabl_tabulate_column_vruled_preset
+ \tabl_tabulate_column_normal}
+
+\def\tabl_tabulate_column_vruled_step#1%
+ {\doifelsenumber{#1}
+ {\global\d_tabl_tabulate_vrulethickness_local#1\d_tabl_tabulate_vrulethickness_default}
+ {\xdef\m_tabl_tabulate_vrule_color_local{#1}}}
+
+\def\tabl_tabulate_column_vruled_yes#1#2[#3]%
+ {\expandafter\gdef\csname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname
+ {\tabl_tabulate_column_vruled_preset
+ \rawprocesscommalist[#3]\tabl_tabulate_column_vruled_step}%
+ \tabl_tabulate_column_normal#1#2}
+
+\def\tabl_tabulate_vrule_reset
+ {\ifcase\c_tabl_tabulate_max_vrulecolumn\else
+ \tabl_tabulate_vrule_reset_indeed
+ \fi}
+
+\def\tabl_tabulate_vrule_reset_indeed
+ {\dofastloopcs\c_tabl_tabulate_max_vrulecolumn\tabl_tabulate_vrule_reset_step
+ \global\c_tabl_tabulate_max_vrulecolumn\zerocount}
+
+\def\tabl_tabulate_vrule_reset_step % undefined or relax
+ {\expandafter\glet\csname\??tabulatevrule\the\fastloopindex\endcsname\undefined}
+
+\appendtoks
+ \tabl_tabulate_vrule_reset
+\to \t_tabl_tabulate_every_after_row
+
+% sometimes more efficient:
+%
+% \def\tabl_tabulate_column_vruled_yes#1#2[#3]%
+% {\rawprocesscommalist[#3]\tabl_tabulate_column_vruled_step
+% \expandafter\xdef\csname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname
+% {\global\d_tabl_tabulate_vrulethickness_local\the\d_tabl_tabulate_vrulethickness_default
+% \noexpand\xdef\noexpand\m_tabl_tabulate_vrule_color_local{\m_tabl_tabulate_vrule_color_local}}%
+% \tabl_tabulate_column_normal#1#2}
+
+\def\tabl_tabulate_column_vruled_normal
+ {\vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
+
+\def\tabl_tabulate_column_vruled_colored
+ {\dousecolorparameter\m_tabl_tabulate_vrule_color
+ \vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
+
+\unexpanded\def\tabl_tabulate_column_vrule_inject_first
+ {\ifcase\d_tabl_tabulate_vrulethickness\else
+ \tabl_tabulate_column_vruled_normal % could be a skip instead
+ \fi
+ \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
+
+\unexpanded\def\tabl_tabulate_column_vrule_inject_second
+ {\ifcase\d_tabl_tabulate_vrulethickness\else
+ \ifx\m_tabl_tabulate_vrule_color\empty
+ \tabl_tabulate_column_vruled_normal
+ \else
+ \tabl_tabulate_column_vruled_colored
+ \fi
+ \fi
+ \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
+
+\let\tabl_tabulate_column_vrule_inject\relax
+
+\appendtoks
+ \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_second
+\to \t_tabl_tabulate_initializers_second
+
+% auto columns
+
+\def\tabl_tabulate_column_inject_auto
+ {\tabl_tabulate_column_normal\zerocount\zerocount
+ \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_columns\relax
+ \expandafter\NR
+ \else
+ \expandafter\ignorespaces % interferes with the more tricky hooks
+ \fi}
+
+\unexpanded\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
+ {\let#1\tabl_tabulate_column_inject_auto
+ \let\\\tabl_tabulate_column_inject_auto} % brrr, will go
+
+\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount}
+\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp}
+\setvalue{\??tabulateseparator\v!small }{\def\m_tabl_tabulate_separator_factor{.25}}
+\setvalue{\??tabulateseparator\v!medium}{\def\m_tabl_tabulate_separator_factor{.5}}
+\setvalue{\??tabulateseparator\v!big }{}
+\setvalue{\??tabulateseparator\v!none }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
+\setvalue{\??tabulateseparator\v!grid }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
+
+\def\tabl_tabulate_column_rule_separator_step#1%
+ {\ifcsname\??tabulateseparator#1\endcsname
+ \lastnamedcs
+ \else
+ \s_tabl_tabulate_separator#1\relax
+ \fi}
+
+\def\tabl_tabulate_column_rule_separator_inject % can be sped up (will do when used frequently)
+ {\bgroup
+ \s_tabl_tabulate_separator\strutdp
+ \ifx\p_distance\empty\else
+ \let\m_tabl_tabulate_separator_factor\plusone
+ \processcommacommand[\p_distance]\tabl_tabulate_column_rule_separator_step
+ \s_tabl_tabulate_separator\m_tabl_tabulate_separator_factor\s_tabl_tabulate_separator
+ \fi
+ % someamble: footer or header: unfortunately a skip can trigger a page break (weird
+ % as we have lots of nobreaks)
+ % \ifconditional\c_tabl_tabulate_someamble\kern\else\vskip\fi\s_tabl_tabulate_separator % new
+ % \directvspacing{\the\s_tabl_tabulate_separator}% new
+ \directvskip\s_tabl_tabulate_separator
+ \egroup}
+
+\def\tabl_tabulate_hrule_spec_ignore#1%
+ {%\glet\currenttabulationlocalhrulecolor\empty
+ %\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
+ \doifelsefastoptionalcheck#1#1}
+
+\def\tabl_tabulate_hrule_spec_pickup#1%
+ {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
+ \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
+ \doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1}
+
+\def\tabl_tabulate_hrule_preset_step#1%
+ {\doifelsenumber{#1}
+ {\global\d_tabl_tabulate_hrulethickness_local#1\d_tabl_tabulate_hrulethickness_default}
+ {\xdef\currenttabulationlocalhrulecolor{#1}}}
+
+\def\tabl_tabulate_hrule_preset#1[#2]%
+ {\rawprocesscommalist[#2]\tabl_tabulate_hrule_preset_step
+ #1}
+
+\def\tabl_tabulate_hrule_inject_normal
+ {\autorule
+ \s!height.5\d_tabl_tabulate_hrulethickness_local
+ \s!depth .5\d_tabl_tabulate_hrulethickness_local
+ \s!left \d_tabl_tabulate_indent
+ \relax}
+
+\def\tabl_tabulate_hrule_inject_colored
+ {\dousecolorparameter\currenttabulationlocalhrulecolor
+ \tabl_tabulate_hrule_inject_normal}
+
+\unexpanded\def\tabl_tabulate_hrule_inject_first
+ {\ifcase\d_tabl_tabulate_hrulethickness_local\else
+ \tabl_tabulate_hrule_inject_normal
+ \fi}
+
+\unexpanded\def\tabl_tabulate_hrule_inject_second
+ {\ifcase\d_tabl_tabulate_hrulethickness_local\else
+ \ifx\currenttabulationlocalhrulecolor\empty
+ \tabl_tabulate_hrule_inject_normal
+ \else
+ \tabl_tabulate_hrule_inject_colored
+ \fi
+ \fi}
+
+\let\tabl_tabulate_hrule_inject\relax
+
+\appendtoks
+ \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_second
+\to \t_tabl_tabulate_initializers_second
+
+%D Color:
+
+% \starttabulate[||p||]
+% \NC test \NC test \NC test \NC \NR
+% \NC test \CC[green] \input tufte \CC[yellow] test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \CC[blue] test \CC[red] test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \CC[gray] test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \CC[blue] test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \CC[magenta] test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \CC[cyan] \dorecurse{10}{\input ward }\NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \CC[yellow] test \NC test \NC \NR
+% \stoptabulate
+
+\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
+ {\begingroup
+ \clf_enablebackgroundalign % was \node_backgrounds_align_initialize
+ \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second
+ \global\settrue\c_tabl_tabulate_has_colors
+ \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_colorcolumn
+ \global\c_tabl_tabulate_max_colorcolumn\c_tabl_tabulate_column
+ \fi
+ \expandafter\xdef\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}%
+ \hpack \thealignbackgroundcolorattr{#1}{}% pack ?
+ \endgroup}
+
+\def\tabl_tabulate_color_repeat_second % for split off lines
+ {\begingroup
+ \scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly !
+ \ifcsname\??tabulatecolor\the\scratchcounter\endcsname
+ % \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ?
+ \hpack \expandafter\thealignbackgroundcolorattr\expandafter{\lastnamedcs}{}% pack ?
+ \fi
+ \endgroup}
+
+\let\tabl_tabulate_color_repeat\relax
+
+\appendtoks
+ \let\tabl_tabulate_color_repeat\relax
+\to \everytabulate
+
+\def\tabl_tabulate_color_reset
+ {\ifcase\c_tabl_tabulate_max_colorcolumn\else
+ \tabl_tabulate_color_reset_indeed
+ \fi}
+
+% \def\tabl_tabulate_color_reset_indeed
+% {\dorecurse\c_tabl_tabulate_max_colorcolumn{\letgvalue{\??tabulatecolor\recurselevel}\undefined}} % slow
+
+\def\tabl_tabulate_color_reset_indeed
+ {\dofastloopcs\c_tabl_tabulate_max_colorcolumn\tabl_tabulate_color_reset_step}
+
+\def\tabl_tabulate_color_reset_step % undefined or empty?
+ {\expandafter\glet\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined}
+
+\appendtoks
+ \tabl_tabulate_color_reset
+\to \t_tabl_tabulate_every_after_row
+
+% \def\tabl_tabulate_register_par_options_indeed
+% {\iftrialtypesetting \else
+% \registerparoptions
+% \ifinsidefloat
+% % that is, an unbreakable one
+% \glet\tabl_tabulate_register_par_options\empty
+% \else
+% % unsafe in crossing pages, at each b...
+% % \glet\tabl_tabulate_register_par_options\empty
+% \fi
+% \fi}
+%
+% \appendtoks
+% \glet\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_indeed
+% \to \everytabulate
+
+\def\tabl_tabulate_register_par_options_first % maybe track here if needed
+ {}
+
+\def\tabl_tabulate_register_par_options_second
+ {\registerparoptions
+ \ifinsidefloat
+ % that is, an unbreakable one
+ \glet\tabl_tabulate_register_par_options\empty
+ \else
+ % unsafe in crossing pages, at each b...
+ % \glet\tabl_tabulate_register_par_options\empty
+ \fi}
+
+\let\tabl_tabulate_register_par_options\relax
+
+\appendtoks
+ \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_second
+\to \t_tabl_tabulate_initializers_second
+
+\appendtoks
+ \tabl_tabulate_register_par_options
+\to \t_tabl_tabulate_every_row
+
+\def\tabl_tabulate_flush_indent_indeed
+ {\hbox to \d_tabl_tabulate_indent % pack ?
+ {% we now have a local hsize, and since we want to
+ % register positional info (i.e. real hsizes) we
+ % need to reconstitute the original hsize
+ \advance\hsize\d_tabl_tabulate_indent
+ % this is indeed rather messy and took a few hours
+ % to dis/uncover
+ \the\t_tabl_tabulate_every_row
+ \hss}}
+
+\def\tabl_tabulate_flush_indent
+ {\ifnum\c_tabl_tabulate_column=\zerocount
+ \tabl_tabulate_flush_indent_indeed
+ \fi}
+
+\def\tabl_tabulate_digits{\digits}
+
+%D Beware, we cannot use \type {\unexpanded} on \type {\HL} cum suis, since \TEX's
+%D hard coded noalign lookahead fails on it! I mistakenly added this for a while.
+
+\setvalue{\??tabulatealigning\v!normal}{0}
+\setvalue{\??tabulatealigning\v!right }{1}
+\setvalue{\??tabulatealigning\v!left }{2}
+\setvalue{\??tabulatealigning\v!middle}{3}
+
+\setvalue{\??tabulateheader\v!repeat}{\plusone}
+\setvalue{\??tabulateheader\v!text }{\plustwo}
+
+\unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
+\unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
+\unexpanded\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
+\unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
+
+\let\tabl_tabulate_bbskip\relax
+\let\tabl_tabulate_eeskip\relax
+\let\tabl_tabulate_bskip \relax
+\let\tabl_tabulate_eskip \relax
+\let\tabl_tabulate_xbskip\relax
+\let\tabl_tabulate_xeskip\relax
+
+\appendtoks
+ \let\tabl_tabulate_bbskip\relax
+ %\let\tabl_tabulate_eeskip\relax % adapted by bskip
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_first
+ \let\tabl_tabulate_eskip \tabl_tabulate_eskip_first
+ \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_first
+ \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_first
+\to \t_tabl_tabulate_initializers_first
+
+\def\tabl_tabulate_baselinecorrection % keep an eye on this one
+ {\def\dobaselinecorrection{\vskip\dimexpr-\prevdepth+\strutdp+\strutdp\relax}% todo: mkiv
+ \baselinecorrection}
+
+% some hack to prevent an allowbreak ... actually we could set up a system then
+% that is dealt with atthe lua end in the skip handler: turn penalties with attributes
+% values into other penalties that get removed
+
+\installcorenamespace{tabulatenobreak}
+
+\def\tabl_tabulate_break_allow{\directvpenalty\zerocount}
+\def\tabl_tabulate_break_maybe{\directvpenalty\zerocount}
+\def\tabl_tabulate_break_no {\directvpenalty\plustenthousand} % ,order:2}}
+
+\let\tabl_tabulate_break_state_set \relax
+\let\tabl_tabulate_break_state_reset \relax
+\let\tabl_tabulate_break_state_allowbreak\tabl_tabulate_break_maybe
+
+% so far
+
+\unexpanded\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount}
+\unexpanded\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount}
+\unexpanded\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone}
+\unexpanded\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo}
+\unexpanded\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo \zerocount}
+\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone}
+\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo}
+
+\unexpanded\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount}
+\unexpanded\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first
+\unexpanded\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake
+
+\unexpanded\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row
+\unexpanded\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break
+
+\unexpanded\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row
+\unexpanded\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break
+
+\unexpanded\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount}
+\unexpanded\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount}
+\unexpanded\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount}
+\unexpanded\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount}
+
+%D Sort of special:
+%D
+%D \startbuffer
+%D \startitemize[n]
+%D \starttabulate[|||||]
+%D \NC p \NC \itemtag \NC q \NC r \NC \NR
+%D \NC p \NC \itemtag \NC q \NC r \NC \NR
+%D \NC p \NC \itemtag \NC q \NC r \NC \NR
+%D \NC p \NC \itemtag \NC q \NC r \NC \NR
+%D \stoptabulate
+%D \stopitemize
+%D
+%D \startitemize[n]
+%D \starttabulate[|||||]
+%D \NI b \NC c \NC d \NC \NR
+%D \NC a \NI c \NC d \NC \NR
+%D \NC a \NC b \NI d \NC \NR
+%D \NC a \NC b \NC c \NI \NR
+%D \stoptabulate
+%D \stopitemize
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\tabl_tabulate_NI_first{\doifelsefastoptionalcheck\tabl_tbl_NI_yes\tabl_tbl_NI_nop}
+
+\def\tabl_tbl_NI_yes[#1]{\NC \itemtag[#1]\NC}
+\def\tabl_tbl_NI_nop {\NC \itemtag \NC}
+
+%D The following shortcut is handy for tables where one needs bold headers:
+
+\unexpanded\def\tabl_tabulate_BC_first
+ {\tabl_tabulate_column_normal\plusone\zerocount
+ \let\fontstyle\globalfontstyle
+ \bf}
+
+\appendtoks
+ \let\VL\tabl_tabulate_VL_first
+ \let\NC\tabl_tabulate_NC_first
+ \let\BC\tabl_tabulate_BC_first
+ \let\RC\tabl_tabulate_RC_first
+ \let\HC\tabl_tabulate_HC_first
+ \let\EQ\tabl_tabulate_EQ_first
+ \let\RQ\tabl_tabulate_RQ_first
+ \let\HQ\tabl_tabulate_HQ_first
+ \let\NG\tabl_tabulate_NG_first
+ \let\NN\tabl_tabulate_NN_first
+ \let\ND\tabl_tabulate_ND_first
+ \let\NR\tabl_tabulate_NR_first
+ \let\NB\tabl_tabulate_NB_first
+ \let\CC\tabl_tabulate_CC_first
+ \let\CL\tabl_tabulate_CL_first
+ \let\CM\tabl_tabulate_CM_first
+ \let\CR\tabl_tabulate_CR_first
+ \let\NI\tabl_tabulate_NI_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\NR\tabl_tabulate_NR_second
+ \let\NB\tabl_tabulate_NB_second
+\to \t_tabl_tabulate_initializers_second
+
+\appendtoks
+ \let\SR\NR
+ \let\FR\NR
+ \let\MR\NR
+ \let\LR\NR
+ \let\AR\NR
+\to \t_tabl_tabulate_initializers_first
+
+\unexpanded\def\tabl_tabulate_NR_common#1#2%
+ {\global\advance\c_tabl_tabulate_noflines\plusone
+ \global\setfalse\c_tabl_tabulate_firstflushed
+ \global\setfalse\c_tabl_tabulate_equal
+ \global\c_tabl_tabulate_column\zerocount
+ \ifconditional#1\relax
+ \tabl_tabulate_break_state_reset
+ \fi
+ \tabl_tabulate_pheight_reset
+ \unskip\unskip\crcr\tabl_tabulate_flush_collected
+ % can we omit the next one in the first run? probably
+ \starttabulatenoalign
+ \the\t_tabl_tabulate_every_after_row
+ #2%
+ \stoptabulatenoalign}
+
+\def\tabl_tabulate_check_penalties
+ {\ifconditional\c_tabl_tabulate_tolerant_break\else
+ \ifnum\c_tabl_tabulate_totalnoflines=\plusone
+ % \tabl_tabulate_break_allow
+ \else
+ \ifconditional\c_tabl_tabulate_someamble \ifcase\c_tabl_tabulate_repeathead \else
+ \tabl_tabulate_break_allow
+ \fi \fi
+ \ifnum\c_tabl_tabulate_noflines=\plusone
+ \tabl_tabulate_nobreak_inject
+ \orelse\ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_minusnoflines
+ \ifnum\c_tabl_tabulate_plines_max<\plustwo
+ \tabl_tabulate_nobreak_inject
+ \else
+ \tabl_tabulate_break_allow % needed with pbreak prevention
+ \fi
+ \else
+ \tabl_tabulate_break_state_allowbreak
+ \fi
+ \fi
+ \fi
+ \global\setfalse\c_tabl_tabulate_firstflushed}
+
+\unexpanded\def\tabl_tabulate_bbskip_second_split_yes
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
+ \ifx\tabl_tabulate_flush_collected_indeed\empty\else
+ \setbox0\hbox
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_eskip_second
+ {\par\egroup
+ \tabl_tabulate_pheight_set
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \tabl_tabulate_splitoff_box}
+
+\unexpanded\def\tabl_tabulate_bskip_second_split_yes
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
+ % first line
+ \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox
+ \bgroup
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
+ \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
+ % \begstrut % interferes with pre-\pars
+ % evt: \appendtoks\begstrut\to\everypar
+ \ignorespaces
+ \let\tabl_tabulate_eskip\tabl_tabulate_eskip_second
+ \else
+ % successive lines
+ \let\tabl_tabulate_eskip\empty
+ \dontcomplain
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \expandafter\tabl_tabulate_splitoff_box
+ \fi}
+
+\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
+\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
+
+\unexpanded\def\tabl_tabulate_flush_second_indeed
+ {\glet\tabl_tabulate_flush_collected_indeed\empty
+ \global\c_tabl_tabulate_column\zerocount
+ \tabl_tabulate_pbreak_check
+ \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step
+ \global\settrue\c_tabl_tabulate_firstflushed}
+
+\unexpanded\def\tabl_tabulate_flush_second_step
+ {\ifvoid\b_tabl_tabulate_current\fastloopindex\else
+ \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}%
+ \fi}
+
+\def\tabl_tabulate_flush_second
+ {\tabulatenoalign{\tabl_tabulate_flush_second_indeed}%
+ \tabl_tabulate_flush_collected_indeed}
+
+\unexpanded\def\tabl_tabulate_bskip_second_split_nop
+ {\vtop\bgroup
+ \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
+ % \begstrut % interferes with pre-\pars
+ % evt: \appendtoks\begstrut\to\everypar
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
+ {\par\verticalstrut
+ \vskip-\struttotal
+ \egroup}
+
+% \let\tabl_tabulate_eskip \relax % adapted by bskip
+% \let\tabl_tabulate_eeskip\relax % adapted by bskip
+
+\appendtoks
+ \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_second
+ \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_second
+ \ifconditional\c_tabl_tabulate_split
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_yes
+ \let\tabl_tabulate_bbskip\tabl_tabulate_bbskip_second_split_yes
+ \else
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_nop
+ \let\tabl_tabulate_eskip \tabl_tabulate_eskip_second_split_nop
+ \fi
+\to \t_tabl_tabulate_initializers_second
+
+% see ***
+%
+% \enabletrackers[nodes.page_vspacing]
+% \starttext
+% \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate
+% \stoptext
+
+\def\tabl_tabulate_XX_none
+ {\starttabulatenoalign
+ \tabl_tabulate_break_state_set
+ \tabl_tabulate_hrule_spec_ignore
+ \stoptabulatenoalign}
+
+\def\tabl_tabulate_FL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_FL_second_indeed}
+\def\tabl_tabulate_ML_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_ML_second_indeed}
+\def\tabl_tabulate_LL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_LL_second_indeed}
+\def\tabl_tabulate_TL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_TL_second_indeed}
+\def\tabl_tabulate_BL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_BL_second_indeed}
+
+\unexpanded\def\tabl_tabulate_FL_second_indeed
+ {\ifinsidefloat\else
+ \doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion
+ \fi
+ \tabl_tabulate_hrule_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \prevdepth\strutdp
+ \tabl_tabulate_nobreak_inject
+ \stoptabulatenoalign}
+
+\def\spac_vspacing_no_topskip % use grouped
+ {\attribute\skipcategoryattribute\plusten}
+
+\unexpanded\def\tabl_tabulate_ML_second_indeed
+ {\tabl_tabulate_break_no
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_break_no
+ \tabl_tabulate_hrule_inject
+ \vskip-\p_rulethickness\relax
+ \begingroup
+ \spac_vspacing_no_topskip
+ \tabl_tabulate_hrule_inject
+ \endgroup
+ \tabl_tabulate_break_no
+ \tabl_tabulate_column_rule_separator_inject
+ \stoptabulatenoalign}
+
+\unexpanded\def\tabl_tabulate_LL_second_indeed
+ {\tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_hrule_inject
+ \ifinsidefloat
+ \tabl_tabulate_inside_inbetween
+ \else
+ \tabl_tabulate_outside_inbetween
+ \fi
+ \stoptabulatenoalign}
+
+\unexpanded\def\tabl_tabulate_TL_second_indeed
+ {\tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_hrule_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ %\prevdepth\strutdp % todo, might differ between TL and BL
+ \tabl_tabulate_nobreak_inject
+ \stoptabulatenoalign}
+
+\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed
+
+\def\tabl_tabulate_HL_second
+ {\csname
+ \ifnum\c_tabl_tabulate_noflines=\zerocount F\orelse
+ \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else
+ M\fi
+ L\endcsname}
+
+\appendtoks
+ \let\FL\tabl_tabulate_XX_none
+ \let\ML\tabl_tabulate_XX_none
+ \let\LL\tabl_tabulate_XX_none
+ \let\TL\tabl_tabulate_XX_none
+ \let\BL\tabl_tabulate_XX_none
+ \let\HL\tabl_tabulate_XX_none
+ \let\HR\tabl_tabulate_XX_none
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\FL\tabl_tabulate_FL_second
+ \let\ML\tabl_tabulate_ML_second
+ \let\LL\tabl_tabulate_LL_second
+ \let\TL\tabl_tabulate_TL_second
+ \let\BL\tabl_tabulate_BL_second
+ \let\HL\tabl_tabulate_HL_second
+ \let\HR\tabl_tabulate_HL_second
+\to \t_tabl_tabulate_initializers_second
+
+% \def\tabulatedoHRfive % horizontal rule line (break untested)
+% {\starttabulatenoalign
+% \glet\dotabulateautoline\dotabulatelinerule
+% %\ifcase#1\or % todo: check what this does
+% \ifnum\noftabulatelines=\zerocount
+% \glet\dotabulateautoline\donothing
+% \else\ifnum\noftabulatelines=\totalnoftabulatelines
+% \glet\dotabulateautoline\donothing
+% \fi\fi
+% %\fi
+% \dotabulatenobreak
+% \stoptabulatenoalign
+% \dotabulateautoline
+% \starttabulatenoalign
+% \tabl_tabulate_break_no
+% \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
+% \ifnum\noftabulatelines=\totalnoftabulatelines
+% \expandafter\dotabulatenobreak
+% \else
+% \expandafter\tabl_tabulate_break_allow
+% \fi
+% \stoptabulatenoalign
+% \dotabulateautoline
+% \starttabulatenoalign
+% \dotabulatenobreak
+% \stoptabulatenoalign}
+
+% \dorecurse{10}{
+% \starttabulate[|l|]
+% \FL
+% \NC first line, bound to next rule \NC \NR
+% \TL
+% \NC bound to previous rule \NC \NR
+% \NC some line \NC \NR
+% \NC some line \NC \NR
+% \NC some line \NC \NR
+% \NC bound to next rule \NC \NR
+% \ML
+% \NC bound to previous rule \NC \NR
+% \NC bound to next rule \NC \NR
+% \BL
+% \NC last line, bound to previous rule \NC \NR
+% \LL
+% \stoptabulate
+% }
+
+% This needs checking:
+
+\def\tabulaterule {\HR} % a rule with lineheight
+\def\tabulateline {\HL} % just a spaced rule
+\def\tabulateautorule{\HR}%
+\def\tabulateautoline{\HL} % no longer different (to be looked into)
+
+%D When support for vertical rules we needed a way to pick up the specification for
+%D the final rule and a \type {|{}} interface was chosen. As a result parsing had to
+%D become more complex and I was not in the mood for messing up the code too much.
+%D Therefore from now on the preamble is split by \LUA. There are definitely more
+%D places where we can use \LUA\ code (for instance in alignment of numbers. The
+%D repeat parser is replace at the \LUA\ end as well.
+
+\let\tabl_tabulate_flush_collected \empty
+\let\tabl_tabulate_flush_collected_indeed\empty
+
+\let\v_tabl_tabulate_align\!!zerocount
+
+\def\tabl_tabulate_check_side_float % new per 29-07-2016
+ {\ifdefined\page_sides_check_floats_indeed
+ \page_sides_check_floats_indeed
+ \ifdim\hangindent>\zeropoint
+ \advance\d_tabl_tabulate_indent\hangindent
+ \fi
+ \fi}
+
+\def\tabl_tabulate_set_local_hsize
+ {\setlocalhsize
+ \hsize\localhsize}
+
+\def\tabl_tabulate_process
+ {\c_tabl_tabulate_pass\plusone
+ \tabl_tabulate_check_full_content
+ \edef\v_tabl_tabulate_align{\ifcsname\??tabulatealigning\p_align\endcsname\lastnamedcs\else0\fi}%
+ \s_tabl_tabulate_first.5\d_tabl_tabulate_unit
+ \s_tabl_tabulate_last\s_tabl_tabulate_first
+ \s_tabl_tabulate_pre\zeropoint
+ \s_tabl_tabulate_post\s_tabl_tabulate_first % was: \zeropoint
+ \global\c_tabl_tabulate_columns\zerocount
+ \global\c_tabl_tabulate_nofauto\zerocount
+ \global\c_tabl_tabulate_noflines\zerocount
+ \c_tabl_tabulate_totalnoflines\zerocount
+ \c_tabl_tabulate_minusnoflines\zerocount
+ \global\d_tabl_tabulate_width_p\zeropoint
+ \global\d_tabl_tabulate_width_w\zeropoint
+ \global\setfalse\c_tabl_tabulate_equal
+ \tabl_tabulate_pheight_reset
+ \tabskip\zeropoint
+ \ifinsidesplitfloat
+ \donetrue
+ \orelse\ifinsidefloat
+ \donefalse
+ \else
+ \donetrue
+ \fi
+ \global\c_tabl_tabulate_repeathead
+ \ifdone
+ \ifcsname\??tabulateheader\tabulationparameter\c!header\endcsname
+ \lastnamedcs
+ \else
+ \zerocount
+ \fi
+ \else
+ \zerocount
+ \fi
+ %
+ \the\t_tabl_tabulate_initializers_first % collect more here
+ %
+ \glet\tabl_tabulate_flush_collected\empty
+ \ifdim\d_tabl_tabulate_margin>\zeropoint
+ \t_tabl_tabulate_preamble
+ {\aligntab
+ \tabl_tabulate_flush_indent
+% \global\advance\c_tabl_tabulate_noflines\plusone
+ \strut
+ \alignmark\alignmark
+ \tabskip\d_tabl_tabulate_margin
+ \strut
+ \aligntab
+ \alignmark\alignmark
+ \tabskip\zeropoint}%
+ \else
+ \t_tabl_tabulate_preamble
+ {\aligntab
+ \tabl_tabulate_flush_indent
+% \global\advance\c_tabl_tabulate_noflines\plusone
+ \strut
+ \alignmark\alignmark
+ \aligntab
+ \alignmark\alignmark
+ \tabskip\zeropoint}%
+ \fi
+ \d_tabl_tabulate_width\zeropoint
+ % these counters are set at the lua end
+ \c_tabl_tabulate_nofcolumns \zerocount
+ \c_tabl_tabulate_has_rule_spec_first\zerocount
+ \c_tabl_tabulate_has_rule_spec_last \zerocount
+ \clf_presettabulate{\detokenizedtabulationparameter\c!format}%
+ %
+ % \edef\totaltabulatecolumns{\the\numexpr3*\c_tabl_tabulate_columns+\plusfour}%
+ \d_tabl_tabulate_width\zeropoint
+ \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
+ \toksapp\t_tabl_tabulate_preamble{%
+ \aligntab\alignmark\alignmark
+ \global\advance\c_tabl_tabulate_column\plusone % maybe just set it already
+ }%
+ \toksapp\t_tabl_tabulate_dummy{%
+ \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
+ }%
+ \global\c_tabl_tabulate_column\zerocount
+ \tabl_tabulate_pheight_reset
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \ifx\p_indenting\v!no
+ \forgetparindent
+ \fi
+ \ifinsidefloat
+ \d_tabl_tabulate_indent\zeropoint
+ \else
+ \tabl_tabulate_check_side_float
+ \tabl_tabulate_set_local_hsize
+ \fi
+ \dontcomplain
+ \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved
+ \everypar\everytabulatepar
+ \setbox\scratchbox\vbox % outside \if because of line counting
+ {\notesenabledfalse
+ \d_tabl_tabulate_indent\zeropoint
+ \settrialtypesetting % very important
+ \anch_backgrounds_text_level_start
+ \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}%
+ \anch_backgrounds_text_level_stop
+ \ifcase\c_anch_backgrounds_text_state\else
+ \global\settrue\tablehaspositions
+ \fi
+ \ifnum\c_tabl_tabulate_nofauto>\zerocount
+ % so, even if the natural size is larger, in the final run, we force the calculated width
+ \d_tabl_tabulate_width\dimexpr\hsize-\wd\scratchbox-\d_tabl_tabulate_width_p-\d_tabl_tabulate_width_w\relax
+ \ifnum\c_tabl_tabulate_nofauto>\zerocount
+ \divide\d_tabl_tabulate_width \c_tabl_tabulate_nofauto\relax
+ \fi
+ \fi
+ \setbox\scratchbox\emptybox % free memory
+ \ifconditional\c_tabl_tabulate_split
+ \splittopskip\strutht
+ \glet\tabl_tabulate_flush_collected_indeed\empty
+ \glet\tabl_tabulate_flush_collected\tabl_tabulate_flush_second
+ \fi
+ \c_tabl_tabulate_totalnoflines\c_tabl_tabulate_noflines
+ \c_tabl_tabulate_minusnoflines\numexpr\c_tabl_tabulate_noflines+\minusone\relax
+ \global\c_tabl_tabulate_noflines\zerocount
+ %
+ \c_tabl_tabulate_pass\plustwo % final pass
+ \the\t_tabl_tabulate_initializers_second % collect more here
+ %
+ \ifx\p_line\v!line
+ \let\HL\HR
+ \let\tabulateautoline\tabulateautorule
+ \let\tabulateline\tabulaterule
+ \fi
+ %
+ \ifcase\c_tabl_tabulate_repeathead
+ \ifinsidesplitfloat
+ \global\setbox\b_tabl_tabulate\vbox \bgroup
+ \else
+ \startframedcontent[\tabulationparameter\c!frame]%
+ \fi
+ \else
+ \global\setbox\b_tabl_tabulate\vbox \bgroup
+ \fi
+ %
+ \dostarttaggedchained\t!tabulate\empty\??tabulation
+ \dostarttagged\t!tabulaterow\empty
+ \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
+ % \everycr\expandafter{\the\everycr\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}%
+ \toksapp\everycr{\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}%
+ \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
+ \dostoptagged
+ \dostoptagged
+ \ifhmode\par\prevdepth\strutdp\fi % nog eens beter, temporary hack
+ \ifx\p_distance\v!grid
+ \vskip-\strutdp % experimental tm-prikkels
+ \fi
+ %
+ \ifcase\c_tabl_tabulate_repeathead
+ \ifinsidesplitfloat
+ \egroup % box
+ \egroup % settings
+ \tabl_split_box\b_tabl_tabulate
+ \else
+ \stopframedcontent
+ \egroup
+ \fi
+ \else
+ \egroup % box
+ \egroup % settings
+ \tabl_split_box\b_tabl_tabulate
+ \fi
+ %
+ \ifinsidefloat
+ \tabl_tabulate_inside_after
+ \else
+ \tabl_tabulate_outside_after
+ \fi
+ \egroup} % whole thing
+
+% \egroup
+
+% \setuptabulate[split=yes,header=text,title=Vervolg van Tabel]
+%
+% % \starttabulatehead
+% % \NC test \NC hans\NC \NR
+% % \stoptabulatehead
+%
+% \starttabulate
+% \NC test \NC \input tufte \relax \NC \NR
+% \NC test \NC \input knuth \relax \NC \NR
+% \NC test \NC \input knuth \relax \NC \NR
+% \NC test \NC \input tufte \relax \NC \NR
+% \NC test \NC \input tufte \relax \NC \NR
+% \NC test \NC \input tufte \relax \NC \NR
+% \stoptabulate
+
+\def\tabl_split_box#1% #1 <> 0/2 / derived from the one in core-ntb.tex
+ {\ifinsidesplitfloat
+ \tabl_split_box_indeed#1%
+ \orelse\ifinsidefloat
+ \unvbox#1%
+ \else
+ \tabl_split_box_indeed#1%
+ \fi}
+
+\def\tabl_split_box_indeed#1%
+ {\resettsplit
+ \def\tsplitminimumfreelines{2}%
+ \def\tsplitminimumfreespace{0pt}%
+ \setbox\tsplitcontent\box#1%
+ \ifcase\c_tabl_tabulate_repeathead\or
+ \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplithead\vbox{\unvbox\tsplithead}%
+ \or
+ \setbox\tsplithead\vbox{\hbox{\strut\tabulationparameter\c!title}}%
+ \fi
+ \handletsplit}
+
+%D \starttyping
+%D \setuptabulate[split=no,rule=line]
+%D
+%D \starttabulate
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \stoptabulate
+%D \stoptyping
+
+%D Spacing:
+%
+% \starttabulate
+% \NC text \NC text \NC \NR
+% \TB[small]
+% \NC text \NC text \NC \NR
+% \TB[4*big]
+% \NC text \NC text \NC \NR
+% \stoptabulate
+
+\def\tabl_tabulate_TB
+ {\starttabulatenoalign
+ \dosingleempty\tabl_tabulate_TB_indeed}
+
+\def\tabl_tabulate_TB_indeed[#1]%
+ {\iffirstargument
+ \blank[#1]
+ \orelse\ifx\m_tabl_tabulate_blank_default\empty
+ \blank
+ \else
+ \blank[\m_tabl_tabulate_blank_default]%
+ \fi
+ \stoptabulatenoalign}
+
+% to be tested:
+%
+% \def\tabl_tabulate_TB
+% {\starttabulatenoalign
+% \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop}
+%
+% \def\tabl_tabulate_TB_yes[#1]%
+% {\blank[#1]
+% \stoptabulatenoalign}
+%
+% \def\tabl_tabulate_TB_nop[#1]%
+% {\blank
+% \stoptabulatenoalign}
+
+\appendtoks
+ \let\TB\tabl_tabulate_TB
+\to \everytabulate
+
+% %D Between alignment lines certain rules apply, and even a simple test can mess
+% %D up a table, which is why we have a special test facilityL
+% %D
+% %D \startbuffer
+% %D \starttabulate[|l|p|]
+% %D \NC 1test \NC test \NC \NR
+% %D \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
+% %D \stoptabulate
+% %D \stopbuffer
+% %D
+% %D \typebuffer \getbuffer
+%
+% \def\tableifelse#1% should be tabulatenoalign then
+% {\tablenoalign
+% {#1%
+% {\aftergroup \firstoftwoarguments}%
+% {\aftergroup\secondoftwoarguments}}}
+%
+% \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
+
+%D Some new trickery:
+%D
+%D \startbuffer
+%D \settrue\c_tabl_tabulate_splitoff_whitespace
+%D
+%D \starttabulate[|p(2cm)|p(2cm)|p(2cm)|]
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \par
+%D test 3b \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[line]
+%D test 3b \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[halfline]
+%D test 3b
+%D \blank[halfline]
+%D test 3c \NC \NR
+%D \NC \blank \NC \blank \NC \blank \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[halfline]
+%D test 3b
+%D \blank[halfline]
+%D test 3c \NC \NR
+%D \NC \blank \NC \blank \NC \NC \NR
+%D \NC test 1a
+%D \par
+%D test 1b
+%D \par
+%D test 1b \NC test 2a
+%D \par
+%D test 2b
+%D \par
+%D test 2b \NC test 3a \NC \NR
+%D \NC test 1a
+%D \blank
+%D test 1b
+%D \par
+%D test 1b \NC test 2a
+%D \par
+%D test 2b
+%D \blank
+%D test 2b \NC test 3a \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \start \getbuffer \stop
+
+% \starttabulatie[|mc|]
+% \NC \digits{100.000,00} \NC\NR
+% \NC \digits{@10.000,00} \NC\NR
+% \NC \digits{@@@.100,00} \NC\NR
+% \NC \digits{@@@.@10,@@} \NC\NR
+% \NC \digits{@@@.@@1,@@} \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|mc|]
+% \ND 100.000,00 \NC\NR
+% \ND @10.000,00 \NC\NR
+% \ND @@@.100,00 \NC\NR
+% \ND @@@.@10,@@ \NC\NR
+% \ND @@@.@@1,@@ \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|c|]
+% \ND $100.000,00$ \NC\NR
+% \ND $@10.000,00$ \NC\NR
+% \ND $@@@.100,00$ \NC\NR
+% \ND $@@@.@10,@@$ \NC\NR
+% \ND $@@@.@@1,@@$ \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|c|]
+% \NC $\digits 100.000,00 $ \NC\NR
+% \NC $\digits @10.000,00 $ \NC\NR
+% \NC $\digits @@@.100,00 $ \NC\NR
+% \NC $\digits @@@.@10,@@ $ \NC\NR
+% \NC $\digits @@@.@@1,@@ $ \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|c|]
+% \NC \digits $100.000,00$ \NC\NR
+% \NC \digits $@10.000,00$ \NC\NR
+% \NC \digits $@@@.100,00$ \NC\NR
+% \NC \digits $@@@.@10,@@$ \NC\NR
+% \NC \digits $@@@.@@1,@@$ \NC\NR
+% \stoptabulatie
+
+%D Predefined categories (moved from core-mis):
+
+\definetabulate
+ [\v!legend]
+ [|emj1|i1|mR|]
+
+\setuptabulate
+ [\v!legend]
+ [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}]
+
+\definetabulate
+ [\v!legend][\v!two]
+ [|emj1|emk1|i1|mR|]
+
+\definetabulate
+ [\v!fact]
+ [|R|ecmj1|i1mR|]
+
+\setuptabulate
+ [\v!fact]
+ [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}]
+
+%D Another example:
+%D
+%D \starttyping
+%D \definetabulate
+%D [whatever]
+%D [|l|r|]
+%D
+%D \definetabulate
+%D [whatever][else]
+%D [|l|c|r|]
+%D
+%D \startwhatever
+%D \NC l \NC r \NC \NR
+%D \NC left \NC right \NC \NR
+%D \stopwhatever
+%D
+%D \startwhatever[else]
+%D \NC l \NC m \NC r \NC \NR
+%D \NC left \NC middle \NC right \NC \NR
+%D \stopwhatever
+%D
+%D \startwhatever[else][format={|c|c|c|c|}]
+%D \NC l \NC m \NC m \NC r \NC \NR
+%D \NC left \NC middle \NC middle \NC right \NC \NR
+%D \stopwhatever
+%D \stoptyping
+
+%D This is needed because we sometimes use the english command in tracing macros. In
+%D fact, most detailed tracing macros that are done with \LUA\ only work in the
+%D english interface anyway.
+
+% \definetabulate[tabulate] \setuptabulate[tabulate][\c!format=\v!none] % so no \v! here
+
+\newconditional\c_tabl_generic
+
+\unexpanded\setuvalue{starttabulate}%
+ {\bgroup % whole thing
+ \settrue\c_tabl_generic
+ \let\currenttabulationparent\empty
+ \dodoubleempty\tabl_start_regular}
+
+\letvalue{stoptabulate}\relax
+
+%D The following helpers are just there because we also have them at the \LUA\ end:
+%D
+%D \startbuffer
+%D \starttabulate[|l|c|r|]
+%D \tabulaterow {a,b,c}
+%D \tabulaterowbold{aa,bb,cc}
+%D \tabulaterowtype{aaa,bbb,ccc}
+%D \tabulaterowtyp {aaaa,bbbb,cccc}
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\tabl_tabulate_compact_row#1#2%
+ {\NC\tabl_tabulate_compact_step#1#2,\end,}
+
+\def\tabl_tabulate_compact_step#1#2#3,%
+ {\ifx#2\end
+ \NR
+ \expandafter\gobbleoneargument
+ \else
+ #1{#2#3}\NC
+ \expandafter\tabl_tabulate_compact_step
+ \fi#1}
+
+\unexpanded\def\tabulaterow {\tabl_tabulate_compact_row\relax}
+\unexpanded\def\tabulaterowbold{\tabl_tabulate_compact_row\bold}
+\unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type}
+\unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ}
+
+%D Here we plug in a row background feature. As we only have support for
+%D \type {frame=name} we can use these variables.
+%D
+%D \starttyping
+%D \startuseMPgraphic{foo}
+%D fill unitsquare
+%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8)
+%D randomized ExHeight
+%D shifted (-ExHeight/8,ExHeight/16)
+%D withcolor RuleColor ;
+%D \stopuseMPgraphic
+%D
+%D \setuptabulate % wel only have frame=name so we can use these:
+%D [background=foo,
+%D backgroundcolor=darkred,
+%D foregroundcolor=white]
+%D
+%D \definelinefiller[foo][mp=foo,color=darkgreen]
+%D \definelinefiller[bar][mp=foo,color=darkred]
+%D
+%D \starttabulate[|||]
+%D \DB foo \BC bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \starttabulate[|||]
+%D \PB foo \BC bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \starttabulate[|||]
+%D \FB[bar] foo \BC bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \startnarrower
+%D \starttabulate[|||]
+%D \DB foo \DB bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D \stopnarrower
+%D
+%D \starttabulate[|||]
+%D \BC foo \BC bar \BC \NR
+%D \NL[magenta] foo \NC bar \NC \NR
+%D \NL[yellow] foo \NC bar \NC \NR
+%D \NL[cyan] foo \NC bar \NC \NR
+%D \NL[gray] foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \starttabulate
+%D \NL[red] foo \NC bar \NC \NR
+%D \NL[green] foo \NL[red] bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NL[blue] foo \NC \input tufte \NC \NR
+%D \NL[gray] foo \NC bar \NC \NR
+%D \NL[yellow] foo \NC bar \NC \NR
+%D \stoptabulate
+%D \stoptyping
+
+% \setuptabulate
+% [\c!background=,
+% \c!backgroundcolor=,
+% \c!foregroundcolor=,
+% \c!foregroundstyle=]
+
+\let\m_table_current_row_background \empty
+\let\m_table_current_row_background_default \empty
+\let\m_table_current_row_background_filler \empty
+\let\m_table_current_row_background_defaultfiller\empty
+\let\m_table_current_row_background_auto \empty
+
+\unexpanded\def\tabl_register_row_background#1%
+ {\xdef\m_table_current_row_background{#1}}
+
+\unexpanded\def\tabl_register_row_background_filler#1%
+ {\xdef\m_table_current_row_background_filler{#1}}
+
+\unexpanded\def\tabl_synchronize_row_background
+ {\iftrialtypesetting\else
+ \ifx\m_table_current_row_background_filler\empty
+ \ifx\m_table_current_row_background\empty
+ % nothing
+ \tabl_synchronize_row_background_dummy
+ \else
+ \tabl_synchronize_row_background_indeed\m_table_current_row_background
+ \fi
+ \else
+ \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_synchronize_row_background_dummy
+ {\iftrialtypesetting\else
+ \begingroup
+ %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint
+ \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint
+ \endgroup
+ \fi}
+
+\unexpanded\def\tabl_synchronize_row_background_indeed#1%
+ {\iftrialtypesetting\else
+ \begingroup
+ \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
+ \dousecolorparameter{#1}%
+ \setbox\scratchbox\hpack{}%
+ %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
+ \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
+ \endgroup
+ \fi}
+
+\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1%
+ {\iftrialtypesetting\else
+ \begingroup
+ \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
+ \node_linefiller_set{#1}%
+ \setbox\scratchbox\hpack{}%
+ %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
+ \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
+ \endgroup
+ \fi}
+
+\appendtoks
+ \glet\m_table_current_row_background\empty
+ \glet\m_table_current_row_background_filler\empty
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+ \global\c_tabl_tabulate_autocolor\zerocount
+ \clf_resetbackgroundrowdata
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \glet\m_table_current_row_background\empty
+ \glet\m_table_current_row_background_filler\empty
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+ \global\c_tabl_tabulate_autocolor\zerocount
+ \clf_resetbackgroundrowdata
+\to \t_tabl_tabulate_initializers_second
+
+\appendtoks
+ \tabl_synchronize_row_background
+\to \t_tabl_tabulate_every_real_row
+
+\appendtoks
+ \glet\m_table_current_row_background\empty
+ \glet\m_table_current_row_background_filler\empty
+\to \t_tabl_tabulate_every_after_row
+
+\unexpanded\def\tabl_tabulate_NL_first[#1]%
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background{#1}%
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_ND_first
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background\m_table_current_row_background_default
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_LB_first[#1]%
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background{#1}%
+ \fi
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_DB_first
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background\m_table_current_row_background_default
+ \fi
+ \let\fontstyle\globalfontstyle
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_NF_first[#1]%
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler{#1}%
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_NP_first
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler\m_table_current_row_background_default_filler
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_FB_first[#1]%
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler{#1}%
+ \fi
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_PB_first
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler\m_table_current_row_background_default_filler
+ \fi
+ \let\fontstyle\globalfontstyle
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_BC_first % overloaded
+ {\tabl_tabulate_column_normal\plusone\zerocount
+ \let\fontstyle\globalfontstyle
+ \ifx\m_table_current_row_background\empty
+ \ifx\m_table_current_row_background_filler\empty
+ \usetabulationstyleandcolor\c!headstyle\c!headcolor
+ \else
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \fi
+ \else
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \fi}
+
+\unexpanded\def\tabl_tabulate_A_first
+ {\global\advance\c_tabl_tabulate_autocolor\plusone
+ \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
+ \ifx\m_table_current_row_background_auto\empty
+ \global\c_tabl_tabulate_autocolor\plusone
+ \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
+ \fi
+ \ifx\m_table_current_row_background_auto\empty
+ \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default
+ \fi
+ \tabl_register_row_background{\m_table_current_row_background_auto}}
+
+\unexpanded\def\tabl_tabulate_NA_first
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \iftrialtypesetting\else
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_tabulate_A_first
+ \fi
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_BA_first
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \iftrialtypesetting\else
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_tabulate_A_first
+ \fi
+ \fi
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\appendtoks
+ \let\NL\tabl_tabulate_NL_first % NC with Line
+ \let\ND\tabl_tabulate_ND_first % NC with Default Line
+ \let\LB\tabl_tabulate_LB_first % BC with Line
+ \let\DB\tabl_tabulate_DB_first % BC with Default Line
+ \let\NF\tabl_tabulate_NF_first % NC with Filler
+ \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler
+ \let\FB\tabl_tabulate_FB_first % BC with Filler
+ \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler
+ \let\NA\tabl_tabulate_NA_first % NC with Auto Line
+ \let\BA\tabl_tabulate_BA_first % NC with Auto Line
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \edef\m_table_current_row_background_default {\tabulateparameter\c!backgroundcolor}%
+ \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}%
+ \let \m_table_current_row_background_auto \empty
+\to \everytabulate
+
+\setuptabulate
+ [\c!headcolor=,
+ \c!headstyle=\bf,
+ \c!backgroundcolor=\tabulationparameter\c!rulecolor,
+ \c!foregroundcolor=,
+ \c!foregroundstyle=\tabulationparameter\c!headstyle]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/type-ini.mklx b/tex/context/base/mkiv/type-ini.mklx
new file mode 100644
index 000000000..67dbb7f6d
--- /dev/null
+++ b/tex/context/base/mkiv/type-ini.mklx
@@ -0,0 +1,618 @@
+%D \module
+%D [ file=type-ini,
+%D version=2001.03.05,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Initialization,
+%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.
+
+\writestatus{loading}{ConTeXt Typescript Macros / Initialization}
+
+\registerctxluafile{type-ini}{}
+
+%D The default fontclass is empty. We could demand always using fontclasses, and
+%D then make the calling macros simplier (always assume fontclass) but apart from
+%D downward compatibility issues, it would make global, class spanning definitions a
+%D pain. Some day we will introduce a default class.
+%D
+%D The \type {type-ini} and \type {font-ini} modules come as a pair and have mutual
+%D dependencies.
+%D
+%D At some point we will only store in memory so some code can go away.
+
+\unprotect
+
+\definesystemvariable {ts} % TypeScript / for the moment we keep this one
+
+\newcount \c_font_typescripts_n_of_preloaded
+\newconditional\c_font_typescripts_quit
+\newtoks \c_font_typescripts_document
+\newconditional\c_font_typescripts_preload
+\newconditional\c_font_typescripts_first_pass \settrue\c_font_typescripts_first_pass
+
+\newif \iftypescriptfound % will become a mode
+\newif \iftracetypescripts
+
+\newtoks \everybeforedefinetypeface
+\newtoks \everyafterdefinetypeface
+
+\let\typescriptfiles \empty
+\let\currenttypescripts\empty
+\let\currenttypefile \empty
+
+\installmacrostack\currenttypefile
+
+\let\typescriptone \empty % public, used in typescripts
+\let\typescripttwo \empty % public, used in typescripts
+\let\typescriptthree\empty % public, used in typescripts
+
+\installmacrostack\typescriptone
+\installmacrostack\typescripttwo
+\installmacrostack\typescriptthree
+
+\let\fontclassstyle \empty
+
+\installmacrostack\fontclassstyle
+
+\let\m_font_typescripts_one \empty
+\let\m_font_typescripts_two \empty
+\let\m_font_typescripts_three\empty
+\let\m_font_typescripts_check\empty
+\let\m_font_typescripts_match\empty
+
+\installmacrostack\m_font_typescripts_one
+\installmacrostack\m_font_typescripts_two
+\installmacrostack\m_font_typescripts_three
+
+\let\t_font_typescripts\relax % uses as synonym
+
+\installcorenamespace{typescriptcache}
+\installcorenamespace{typescriptfiles}
+\installcorenamespace{typescriptonce}
+\installcorenamespace{typescriptsynonyms}
+\installcorenamespace{typescriptprefix}
+\installcorenamespace{typescriptinheritances}
+\installcorenamespace{typescriptdefaultstyles}
+\installcorenamespace{typescriptrelatives}
+
+\definesystemvariable{ts} % TypeScript
+
+% tricky ... here we push/pop ... so \let
+
+\let\typescriptmethod\plusone % 1: empty==all==true 2: empty==false
+\let\typescriptstate \plustwo % 1: process 2: store
+
+\installmacrostack\typescriptmethod
+\installmacrostack\typescriptstate
+
+\unexpanded\def\starttypescriptcollection
+ {\dosingleempty\font_typescripts_collection_start}
+
+\def\font_typescripts_collection_start[#tag]%
+ {}
+
+\let\stoptypescriptcollection\relax
+
+\unexpanded\def\usetypescriptfile[#filename]%
+ {\doifelse{#filename}\v!reset
+ {\let\typescriptfiles\empty}
+ {\splitfilename{#filename}%
+ \addtocommalist\splitoffbase\typescriptfiles}}
+
+\unexpanded\def\usetypescript {\dotripleempty\font_typescripts_use_one}
+\unexpanded\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two}
+
+\def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use}
+\def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use}
+
+\installmacrostack\stoptypescript
+
+\unexpanded\def\font_typescripts_use[#one][#two][#three]%
+ {\push_macro_m_font_typescripts_one
+ \push_macro_m_font_typescripts_two
+ \push_macro_m_font_typescripts_three
+ \edef\m_font_typescripts_one {\truetypescript{#one}}%
+ \edef\m_font_typescripts_two {\truetypescript{#two}}%
+ \edef\m_font_typescripts_three{\truetypescript{#three}}%
+ \push_macro_typescriptone
+ \push_macro_typescripttwo
+ \push_macro_typescriptthree
+ \push_macro_typescriptmethod
+ \push_macro_typescriptstate
+ \push_macro_stoptypescript
+ \typescriptfoundfalse
+ \let\typescriptstate\plusone % why
+ \iftracetypescripts
+ \writestatus\m!fonts{request: [\m_font_typescripts_one] [\m_font_typescripts_two] [\m_font_typescripts_three]}%
+ \fi
+ \ifhmode
+ \font_typescripts_use_inline
+ \else
+ \font_typescripts_use_display
+ \fi
+ \setfalse\c_font_typescripts_first_pass
+ \pop_macro_stoptypescript
+ \pop_macro_typescriptstate
+ \pop_macro_typescriptmethod
+ \pop_macro_typescriptthree
+ \pop_macro_typescripttwo
+ \pop_macro_typescriptone
+ \pop_macro_m_font_typescripts_three
+ \pop_macro_m_font_typescripts_two
+ \pop_macro_m_font_typescripts_one}
+
+\def\font_typescripts_use_display
+ {\processcommacommand[\typescriptfiles]\font_typescripts_load_file
+ \the\c_font_typescripts_document}
+
+\let\font_typescripts_use_inline\font_typescripts_use_display
+
+\unexpanded\def\preloadtypescripts
+ {\ifproductionrun\settrue\c_font_typescripts_preload\fi}
+
+\prependtoks
+ \preloadtypescripts
+\to \everyjob
+
+\unexpanded\def\loadtypescriptfile[#1]%
+ {\push_macro_typescriptstate
+ \let\typescriptstate\plustwo % assumes 2 at the outer level
+ \clf_loadtypescriptfile{#1}%
+ \pop_macro_typescriptstate}
+
+\unexpanded\def\loadfoundtypescriptfile#1%
+ {\startreadingfile
+ \unprotect
+ \pushendofline
+ \input{#1}%
+ \popendofline
+ \protect
+ \stopreadingfile}
+
+\unexpanded\def\quittypescriptscanning
+ {\settrue\c_font_typescripts_quit} % public
+
+\def\font_typescripts_start_store#definitions\stoptypescript
+ {\global\advance\c_font_typescripts_n_of_preloaded\plusone
+ \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
+ {\starttypescript#definitions\stoptypescript}%
+ \gtoksapp\t_font_typescripts\expandafter
+ {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+
+\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection
+ {\global\advance\c_font_typescripts_n_of_preloaded\plusone
+ \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
+ {\starttypescriptcollection#definitions\stoptypescriptcollection}%
+ \gtoksapp\t_font_typescripts\expandafter
+ {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+
+\def\font_typescripts_load_file#filename%
+ {\setfalse\c_font_typescripts_quit
+ \push_macro_currenttypefile
+ \def\currenttypefile{#filename}%
+ \ifconditional\c_font_typescripts_preload
+ \font_typescript_process_typescript_file_and_store
+ \else
+ \font_typescript_process_typescript_file
+ \fi
+ \pop_macro_currenttypefile
+ \ifconditional\c_font_typescripts_quit
+ \quitcommalist
+ \setfalse\c_font_typescripts_quit
+ \fi}
+
+\def\font_typescript_process_typescript_file_and_store
+ {\expandafter\let\expandafter\t_font_typescripts\csname\??typescriptfiles\currenttypefile\endcsname
+ \ifx\t_font_typescripts\relax
+ \font_typescript_process_typescript_store_indeed
+ \fi
+ \the\t_font_typescripts}
+
+\def\font_typescript_process_typescript_store_indeed
+ {\newtoks\t_font_typescripts % is \relaxed elsewhere
+ \begingroup
+ \let\starttypescript \font_typescripts_start_store
+ \let\starttypescriptcollection\font_typescripts_collection_start_store
+ \font_typescript_process_typescript_file
+ \endgroup
+ \expandafter\let\csname\??typescriptfiles\currenttypefile\endcsname\t_font_typescripts}
+
+\def\font_typescript_process_typescript_file
+ {\clf_doprocesstypescriptfile{\currenttypefile}}
+
+\unexpanded\def\usetypescriptonce
+ {\dotripleempty\font_typescripts_use_once}
+
+\def\font_typescripts_use_once[#one][#two][#three]%
+ {\ifcsname\??typescriptonce#one:#two:#three\endcsname
+ \writestatus\m!fonts{once (#one) (#two) (#three)}%
+ \else
+ \expandafter\let\csname\??typescriptonce#one:#two:#three\endcsname\relax
+ \font_typescripts_use[#one][#two][#three]%
+ \fi}
+
+% \definetypescriptsynonym[lbr][cmr]
+
+\unexpanded\def\definetypescriptsynonym
+ {\dodoubleempty\font_typescripts_synonym_define}
+
+\def\font_typescripts_synonym_define[#name][#synonym]%
+ {\ifsecondargument\setevalue{\??typescriptsynonyms#name}{#synonym}\fi}
+
+\def\truetypescript#name% recursive so no \lastnamedcs
+ {\ifcsname\??typescriptsynonyms#name\endcsname
+ %\expandafter\truetypescript\csname\??typescriptsynonyms#name\endcsname
+ \expandafter\truetypescript\lastnamedcs
+ \else
+ #name%
+ \fi}
+
+% script [serif] [default] [size]
+% script [serif] [computer-modern] [size]
+% script [serif] [computer-modern] [ec]
+% script [serif] [computer-modern] [name]
+% script [serif] [computer-modern] [special]
+
+\prependtoks
+ \settrue\c_font_typescripts_first_pass
+\to \everyjob
+
+\unexpanded\def\starttypescript
+ {\ifcase\typescriptstate
+ % 0 = skip
+ \expandafter\font_typescripts_start_gobble
+ \or
+ % 1 = process
+ \expandafter\font_typescripts_start_process
+ \or
+ % 2 = store
+ \expandafter\font_typescripts_start_document
+ \else
+ % ? = skip
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_start_gobble#definitions\stoptypescript{}
+
+\def\font_typescripts_start_document#definitions\stoptypescript
+ {\toksapp\c_font_typescripts_document{\starttypescript#definitions\stoptypescript}}
+
+\def\font_typescripts_start_process % could be a faster \doifelsenextoptionalif needed
+ {\let\typescriptone \m_font_typescripts_one
+ \let\typescripttwo \m_font_typescripts_two
+ \let\typescriptthree\m_font_typescripts_three
+ \let\m_font_typescripts_match\empty
+ \doifelsenextoptionalcs\font_typescripts_start_process_one\font_typescripts_start_process_all}
+
+\def\font_typescripts_start_process_all % could be a \let
+ {\ifconditional\c_font_typescripts_first_pass
+ \expandafter\font_typescripts_start_process_indeed
+ \else
+ % skip this since it may do unwanted resets, like
+ % setting symbolic font names to unknown, especially
+ % in run time user type scripts
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_show_match
+ {\writestatus\m!fonts{match:\ifx\currenttypefile\relax\space *\fi \m_font_typescripts_match}}
+
+\def\font_typescripts_start_process_yes
+ {\ifdone
+ \typescriptfoundtrue
+ \iftracetypescripts\font_typescripts_show_match\fi
+ \expandafter\font_typescripts_start_process_indeed
+ \else
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_start_process_one
+ {\font_typescripts_check\m_font_typescripts_one\typescriptone\font_typescripts_start_process_again_one}
+
+\def\font_typescripts_start_process_two
+ {\font_typescripts_check\m_font_typescripts_two\typescripttwo\font_typescripts_start_process_again_two}
+
+\def\font_typescripts_start_process_three
+ {\font_typescripts_check\m_font_typescripts_three\typescriptthree\font_typescripts_start_process_again_three}
+
+\def\font_typescripts_start_process_again_one
+ {\doifelsenextoptionalcs\font_typescripts_start_process_two\font_typescripts_start_process_yes}
+
+\def\font_typescripts_start_process_again_two
+ {\doifelsenextoptionalcs\font_typescripts_start_process_three\font_typescripts_start_process_yes}
+
+\let\font_typescripts_start_process_again_three\font_typescripts_start_process_yes
+
+\def\font_typescripts_start_process_indeed
+ {\push_macro_fontclass}
+
+\unexpanded\def\stoptypescript
+ {\pop_macro_fontclass}
+
+\def\font_typescripts_check#asked#target#followup[#value]% script use value next
+ {\donefalse
+ \edef\m_font_typescripts_check{#value}%
+ \ifx\m_font_typescripts_check\empty % no longer needed / met
+ \ifcase\typescriptmethod\or\donetrue\fi
+ \orelse\ifx#asked\s!all
+ \donetrue
+ \orelse\ifx\m_font_typescripts_check\s!all
+ \donetrue
+ \orelse\ifx#asked\m_font_typescripts_check % saves 10% trace so probably faster too
+ \donetrue
+ \let#target\m_font_typescripts_check
+ \else
+ \doifelsecommon\m_font_typescripts_check#asked\donetrue\donefalse
+ \ifdone
+ \let#target\commalistelement
+ \fi
+ \fi
+ \ifdone
+ \iftracetypescripts\extendtypescriptmatch\fi
+ \expandafter#followup%
+ \else
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\extendtypescriptmatch
+ {\edef\m_font_typescripts_match{\m_font_typescripts_match\space[\m_font_typescripts_check]}}
+
+%D Map files will go away in \LUATEX, but till that happens we use stripped down
+%D support for loading them.
+
+\unexpanded\def\loadmapfile{\dosingleempty\font_map_load_file}
+\unexpanded\def\loadmapline{\dodoubleempty\font_map_load_line}
+
+\def\font_map_load_file[#filename]%
+ {\clf_loadmapfile{#filename}}
+
+\def\font_map_load_line[#kind][#data]%
+ {\clf_loadmapline{#kind}{#data}}
+
+\unexpanded\def\forgetmapfiles
+ {\clf_resetmapfiles}
+
+% \prependtoks
+% \loadmapfile[mkiv-base.map]% can't we preload this one?
+% \to \everystarttext
+
+%D A handy shortcut:
+
+% \definetypescriptprefix[serif][Serif]
+% \definetypescriptprefix[sans] [Sans]
+% \definetypescriptprefix[mono] [Mono]
+%
+% \starttypescript [serif,sans,mono] [handling,hanging,hz] [pure,normal,hz,quality]
+% \setupfontsynonym [\typescriptprefix\typescriptone] [handling=\typescriptthree]
+% \stoptypescript
+
+\unexpanded\def\definetypescriptprefix
+ {\dodoubleargument\font_typescripts_define_prefix}
+
+\def\font_typescripts_define_prefix[#name][#prefix]%
+ {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global
+
+\def\typescriptprefix#name%
+ %{\ifcsname\??typescriptprefix#name\endcsname\csname\??typescriptprefix#name\endcsname\else#name\fi}
+ {\ifcsname\??typescriptprefix#name\endcsname\lastnamedcs\else#name\fi}
+
+% defining typefaces:
+%
+% \definetypeface [joke] [rm]
+% \definetypeface [joke] [rm] [settings]
+% \definetypeface [joke] [rm] [serif] [lucida]
+% \definetypeface [joke] [rm] [serif] [lucida] [size]
+% \definetypeface [joke] [rm] [serif] [lucida] [size] [settings]
+% \definetypeface [joke] [specification]
+
+\unexpanded\def\definetypeface
+ {\dosixtupleargument\font_typefaces_define}
+
+\appendtoks
+ \font_helpers_reset_fontclass_math_families\fontclass
+\to \everybeforedefinetypeface
+
+%D This hooks into the font switcher:
+
+\settrue\autotypescripts
+
+\unexpanded\def\trycurrentfontclass#typeface%
+ {\ifconditional\autotypescripts
+ \usetypescript[#typeface]%
+ \ifcsname\??fontclassyes#typeface\endcsname
+ \edef\fontclass{#typeface}%
+ \else
+ \iftracetypescripts\writestatus\m!fonts{auto load typescript file 1: [#typeface]}\fi
+ \usetypescriptfile[#typeface]%
+ \usetypescript[#typeface]%
+ \ifcsname\??fontclassyes#typeface\endcsname
+ \edef\fontclass{#typeface}%
+ \else
+ % todo: message
+ \letvalueempty{\??fontclassnop#typeface}%
+ \fi
+ \fi
+ \else
+ % todo: message
+ \letvalueempty{\??fontclassnop#typeface}%
+ \fi}
+
+%D Now we define:
+
+\def\font_typefaces_define
+ {\iffifthargument
+ \expandafter\font_typefaces_define_a
+ \orelse\iffourthargument
+ \expandafter\font_typefaces_define_b
+ \orelse\ifthirdargument
+ \expandafter\font_typefaces_define_c
+ \else
+ \expandafter\font_typefaces_define_d
+ \fi}
+
+\def\font_typefaces_define_a[#name][#style][#fontshape][#fontname][#fontsize][#settings]%
+ {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi
+ \font_typefaces_define_indeed[#name][#style]%
+ \font_typefaces_defining_start{#name}{#style}{#settings}%
+ \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]%
+ \iftypescriptfound
+ % we're okay
+ \orelse\ifconditional\autotypescripts
+ \iftracetypescripts\writestatus\m!fonts{auto load typescript file 2: [#fontname]}\fi
+ \usetypescriptfile[#fontname]%
+ \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]%
+ \fi
+ \font_typescripts_use_one[#fontshape][#fontsize][\s!size]%
+ \font_typefaces_defining_stop}
+
+\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#dummya][#dummyb]%
+ {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#dummyb]}
+
+\def\font_typefaces_define_c[#name][#style][#dummya][#dummyb][#dummyc][#dummyd]%
+ {\font_typefaces_define_indeed[#name][#style]}
+
+\def\font_typefaces_define_d[#name][#specification][#dummya][#dummyb][#dummyc][#dummyd]% use definitions in lfg file
+ {\clf_definetypeface{#name}{#specification}}
+
+\def\font_typefaces_define_indeed[#name][#style]% saveguard against redefinition
+ {\doifsomething{#name}
+ {\ifcsname\??typescriptdefaultstyles#name\endcsname \else
+ \registerfontclass{#name}%
+ \setxvalue{\??typescriptdefaultstyles#name}{#style}%
+ \fi
+ \ifcsname#name\endcsname \else
+ \setugvalue{#name}{\switchtotypeface[#name][#style]}%
+ \fi}}
+
+\def\font_typefaces_defining_start#name#style#settings%
+ {\let\@@tsrscale \!!plusone % as we push/pop
+ \let\@@tsfeatures \empty
+ \let\@@tsfallbacks \empty
+ \let\@@tsgoodies \empty
+ \let\@@tsdirection \empty
+ \let\@@tsdesignsize\empty
+ \geteparameters[\??ts][#settings]% todo raw
+ \push_macro_fontclass
+ \push_macro_fontclassstyle
+ \setcurrentfontclass{#name}%
+ \savefontclassparameters{#style}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies\@@tsdesignsize\@@tsdirection
+ \the\everybeforedefinetypeface}
+
+\def\tsvar#key#default% undocumented and unofficial
+ {\expandafter\ifx\csname\??ts#key\endcsname\empty
+ #default%
+ \else
+ \csname\??ts#key\endcsname
+ \fi}
+
+\def\font_typefaces_defining_stop
+ {\the\everyafterdefinetypeface
+ \pop_macro_fontclassstyle
+ \pop_macro_fontclass}
+
+\def\dofastdefinetypeface#name#style#fontshape#fontsize#settings% called from the lua end (via case d)
+ {\font_typefaces_define_indeed[#name][#style]%
+ \font_typefaces_defining_start{#name}{#style}{#settings}%
+ \font_typescripts_use_one[#fontshape][#fontsize][\s!size]%
+ \font_typefaces_defining_stop}
+
+\unexpanded\def\setuptypeface% [class] [settings]
+ {\dodoubleempty\font_typefaces_setup}
+
+\unexpanded\def\switchtotypeface% [class] [settings]
+ {\dodoubleempty\font_typefaces_switch}
+
+\def\font_typefaces_setup[#class][#settings]%
+ {\setcurrentfontclass{#class}%
+ \let\globalfontclass\fontclass
+ \ifsecondargument
+ \setupbodyfont[#settings]%
+ \orelse\ifx\fontclass\empty
+ \setupbodyfont[\s!rm]%
+ \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+ \expandafter\setupbodyfont\expandafter[\lastnamedcs]%
+ \else
+ \setupbodyfont[\s!rm]%
+ \fi
+ \ifmmode\mr\else\tf\fi} % needed ?
+
+\def\font_typefaces_switch[#class][#settings]%
+ {\setcurrentfontclass{#class}%
+ \let\globalfontclass\globalfontclass
+ \ifsecondargument
+ \switchtobodyfont[#settings]%
+ \orelse\ifx\fontclass\empty
+ \switchtobodyfont[\s!rm]%
+ \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+ \expandafter\switchtobodyfont\expandafter[\lastnamedcs]%
+ \else
+ \switchtobodyfont[\s!rm]%
+ \fi
+ \ifmmode\mr\else\tf\fi} % needed ?
+
+%D For Taco:
+%D
+%D \starttyping
+%D \inherittypeface[palatino][rm][postscript]
+%D \inherittypeface[palatino][rm][\fontclass]
+%D \inherittypeface[palatino][rm] % == \fontclass
+%D \inherittypeface[palatino] % == [rm,ss,tt,mm]
+%D \stoptyping
+
+\unexpanded\def\inherittypeface
+ {\dotripleempty\font_typescripts_inherit_indeed}
+
+\def\font_typescripts_inherit_indeed[#name][#styles][#parentclass]%
+ {\doifelsenothing{#styles}
+ {\font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]}
+ {\doifnot{#name}{#parentclass}
+ {\glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed
+ \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}%
+ \processcommalist[#styles]\font_typescripts_inherit_check_step}}}
+
+\let\font_typescripts_inherit_check_step\relax
+
+%D This hooks into the font mechanism with:
+
+\def\font_typescripts_inherit_check_indeed#name% called often
+ {\ifcsname\??typescriptinheritances\fontclass:#name\endcsname
+ %\expandafter\let\expandafter\fontclass\csname\??typescriptinheritances\fontclass:#name\endcsname
+ \expandafter\let\expandafter\fontclass\lastnamedcs
+ \fi}
+
+\let\font_typescripts_inherit_check\gobbleoneargument
+
+% not yet:
+%
+% \def\font_helpers_check_relative_font_id
+% {\ifcsname\??typescriptrelatives\fontclass\endcsname
+% \expandafter\let\expandafter\relativefontid\csname\??typescriptrelatives\fontclass\endcsname
+% \else
+% \expandafter\normalxdef\csname\??typescriptrelatives\fontclass\endcsname{\the\lastfontid}%
+% \let\relativefontid\minusone
+% \fi}
+
+\def\v_font_string_d % default fontstyle (expands to \s!Serif in font-ini)
+ {\expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!rm \s!Serif \else
+ \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!ss \s!Sans \else
+ \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+\unexpanded\def\font_helpers_set_fontstyle_of_fontclass
+ {\ifx\fontclass\empty
+ \let\fontstyle\s!rm
+ \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ %\edef\fontstyle{\csname\??typescriptdefaultstyles\fontclass\endcsname}%
+ \edef\fontstyle{\lastnamedcs}%
+ \else
+ \let\fontstyle\s!rm
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/type-ini.mkvi b/tex/context/base/mkiv/type-ini.mkvi
index 8cb370f58..6f0a9a9da 100644
--- a/tex/context/base/mkiv/type-ini.mkvi
+++ b/tex/context/base/mkiv/type-ini.mkvi
@@ -15,13 +15,13 @@
\registerctxluafile{type-ini}{}
-%D The default fontclass is empty. We could demand always using fontclasses,
-%D and then make the calling macros simplier (always assume fontclass) but
-%D apart from downward compatibility issues, it would make global, class
-%D spanning definitions a pain. Some day we will introduce a default class.
+%D The default fontclass is empty. We could demand always using fontclasses, and
+%D then make the calling macros simplier (always assume fontclass) but apart from
+%D downward compatibility issues, it would make global, class spanning definitions a
+%D pain. Some day we will introduce a default class.
%D
-%D The \type {type-ini} and \type {font-ini} modules come as a pair and have
-%D mutual dependencies.
+%D The \type {type-ini} and \type {font-ini} modules come as a pair and have mutual
+%D dependencies.
%D
%D At some point we will only store in memory so some code can go away.
@@ -183,8 +183,8 @@
\preloadtypescripts
\to \everyjob
-% The next will change .. we can load a file inside a typescript but as the state is
-% 1 then, it doesn't get stored without doing that explicitly
+%D The next will change .. we can load a file inside a typescript but as the state is
+%D 1 then, it doesn't get stored without doing that explicitly
\unexpanded\def\loadtypescriptfile[#1]%
{\push_macro_typescriptstate
@@ -412,8 +412,8 @@
\def\extendtypescriptmatch
{\edef\m_font_typescripts_match{\m_font_typescripts_match\space[\m_font_typescripts_check]}}
-%D Map files will go away in \LUATEX, but till that happens we
-%D use stripped down support for loading them.
+%D Map files will go away in \LUATEX, but till that happens we use stripped down
+%D support for loading them.
\unexpanded\def\loadmapfile{\dosingleempty\font_map_load_file}
\unexpanded\def\loadmapline{\dodoubleempty\font_map_load_line}
diff --git a/tex/context/base/mkiv/util-sci.lua b/tex/context/base/mkiv/util-sci.lua
index d58b3387f..a3fcbc928 100644
--- a/tex/context/base/mkiv/util-sci.lua
+++ b/tex/context/base/mkiv/util-sci.lua
@@ -40,7 +40,7 @@ local knownlexers = {
mkii = "tex",
bib = "bibtex",
cld = "tex",
- lua = "lua",
+ lua = "lua", lmt = "lua",
lfg = "lua", lus = "lua", luv = "lua",
mp = "mps",
mpiv = "mps",
diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua
index 5470c2fd6..ad22302df 100644
--- a/tex/context/base/mkiv/util-str.lua
+++ b/tex/context/base/mkiv/util-str.lua
@@ -584,6 +584,26 @@ local template = [[
return function(%s) return %s end
]]
+-- this might move
+
+local pattern = Cs(Cc('"') * (
+ (1-S('"\\\n\r'))^1
+ + P('"') / '\\"'
+ + P('\\') / '\\\\'
+ + P('\n') / '\\n'
+ + P('\r') / '\\r'
+)^0 * Cc('"'))
+
+patterns.escapedquotes = pattern
+
+function string.escapedquotes(s)
+ return lpegmatch(pattern,s)
+end
+
+-- print(string.escapedquotes('1\\23\n"'))
+
+-- but for now here
+
local preamble = ""
local environment = {
@@ -611,6 +631,7 @@ local environment = {
formattedfloat = number.formattedfloat,
stripzero = patterns.stripzero,
stripzeros = patterns.stripzeros,
+ escapedquotes = string.escapedquotes,
FORMAT = string.f9,
}
@@ -685,11 +706,13 @@ local format_q = function()
-- lua 5.3 has a different q than lua 5.2 (which does a tostring on numbers)
-- return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n)
return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n)
+ -- return format("(a%s ~= nil and escapedquotes(tostring(a%s)) or '')",n,n)
end
-local format_Q = function() -- can be optimized
+local format_Q = function() -- fast escaping
n = n + 1
- return format("format('%%q',tostring(a%s))",n)
+-- return format("format('%%q',tostring(a%s))",n)
+ return format("escapedquotes(tostring(a%s))",n)
end
local format_i = function(f)
diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua
index 2f425cca3..f970d8ace 100644
--- a/tex/context/base/mkiv/util-tab.lua
+++ b/tex/context/base/mkiv/util-tab.lua
@@ -314,21 +314,21 @@ end
-- best keep [%q] keys (as we have some in older applications i.e. saving user data (otherwise
-- we also need to check for reserved words)
-local f_hashed_string = formatters["[%q]=%q,"]
-local f_hashed_number = formatters["[%q]=%s,"]
-local f_hashed_boolean = formatters["[%q]=%l,"]
-local f_hashed_table = formatters["[%q]="]
+local f_hashed_string = formatters["[%Q]=%Q,"]
+local f_hashed_number = formatters["[%Q]=%s,"]
+local f_hashed_boolean = formatters["[%Q]=%l,"]
+local f_hashed_table = formatters["[%Q]="]
-local f_indexed_string = formatters["[%s]=%q,"]
+local f_indexed_string = formatters["[%s]=%Q,"]
local f_indexed_number = formatters["[%s]=%s,"]
local f_indexed_boolean = formatters["[%s]=%l,"]
local f_indexed_table = formatters["[%s]="]
-local f_ordered_string = formatters["%q,"]
+local f_ordered_string = formatters["%Q,"]
local f_ordered_number = formatters["%s,"]
local f_ordered_boolean = formatters["%l,"]
-function table.fastserialize(t,prefix)
+function table.fastserialize(t,prefix) -- todo, move local function out
-- prefix should contain the =
-- not sorted
@@ -525,27 +525,27 @@ local f_start_key_nop = formatters["%w{"]
local f_stop = formatters["%w},"]
local f_key_num_value_num = formatters["%w[%s]=%s,"]
-local f_key_str_value_num = formatters["%w[%q]=%s,"]
+local f_key_str_value_num = formatters["%w[%Q]=%s,"]
local f_key_boo_value_num = formatters["%w[%l]=%s,"]
-local f_key_num_value_str = formatters["%w[%s]=%q,"]
-local f_key_str_value_str = formatters["%w[%q]=%q,"]
-local f_key_boo_value_str = formatters["%w[%l]=%q,"]
+local f_key_num_value_str = formatters["%w[%s]=%Q,"]
+local f_key_str_value_str = formatters["%w[%Q]=%Q,"]
+local f_key_boo_value_str = formatters["%w[%l]=%Q,"]
local f_key_num_value_boo = formatters["%w[%s]=%l,"]
-local f_key_str_value_boo = formatters["%w[%q]=%l,"]
+local f_key_str_value_boo = formatters["%w[%Q]=%l,"]
local f_key_boo_value_boo = formatters["%w[%l]=%l,"]
local f_key_num_value_not = formatters["%w[%s]={},"]
-local f_key_str_value_not = formatters["%w[%q]={},"]
+local f_key_str_value_not = formatters["%w[%Q]={},"]
local f_key_boo_value_not = formatters["%w[%l]={},"]
local f_key_num_value_seq = formatters["%w[%s]={ %, t },"]
-local f_key_str_value_seq = formatters["%w[%q]={ %, t },"]
+local f_key_str_value_seq = formatters["%w[%Q]={ %, t },"]
local f_key_boo_value_seq = formatters["%w[%l]={ %, t },"]
local f_val_num = formatters["%w%s,"]
-local f_val_str = formatters["%w%q,"]
+local f_val_str = formatters["%w%Q,"]
local f_val_boo = formatters["%w%l,"]
local f_val_not = formatters["%w{},"]
local f_val_seq = formatters["%w{ %, t },"]
@@ -554,7 +554,7 @@ local f_fin_seq = formatters[" %, t }"]
local f_table_return = formatters["return {"]
local f_table_name = formatters["%s={"]
local f_table_direct = formatters["{"]
-local f_table_entry = formatters["[%q]={"]
+local f_table_entry = formatters["[%Q]={"]
local f_table_finish = formatters["}"]
----- f_string = formatters["%q"]
diff --git a/tex/context/interface/mkii/keys-it.xml b/tex/context/interface/mkii/keys-it.xml
index c852ae515..ac2816578 100644
--- a/tex/context/interface/mkii/keys-it.xml
+++ b/tex/context/interface/mkii/keys-it.xml
@@ -150,6 +150,7 @@
<cd:variable name='comment' value='commento'/>
<cd:variable name='component' value='componente'/>
<cd:variable name='compressseparator' value='compressseparator'/>
+ <cd:variable name='compressstopper' value='compressstopper'/>
<cd:variable name='concept' value='concetto'/>
<cd:variable name='construction' value='construction'/>
<cd:variable name='content' value='indice'/>
@@ -480,6 +481,7 @@
<cd:variable name='sectionnumber' value='numerosezione'/>
<cd:variable name='see' value='vedi'/>
<cd:variable name='selectfont' value='selectfont'/>
+ <cd:variable name='separator' value='separator'/>
<cd:variable name='september' value='settembre'/>
<cd:variable name='serif' value='serif'/>
<cd:variable name='serifbold' value='serifbold'/>
@@ -641,6 +643,7 @@
<cd:constant name='aligntitle' value='allineatitolo'/>
<cd:constant name='alternative' value='alternativa'/>
<cd:constant name='anchor' value='anchor'/>
+ <cd:constant name='anchoring' value='anchoring'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arguments' value='arguments'/>
@@ -738,7 +741,9 @@
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
<cd:constant name='compressdistance' value='compressdistance'/>
+ <cd:constant name='compressmethod' value='compressmethod'/>
<cd:constant name='compressseparator' value='compressseparator'/>
+ <cd:constant name='compressstopper' value='compressstopper'/>
<cd:constant name='concerns' value='concerns'/>
<cd:constant name='connector' value='connector'/>
<cd:constant name='continue' value='continua'/>
diff --git a/tex/context/interface/mkiv/context-en.xml b/tex/context/interface/mkiv/context-en.xml
index 9b1c7f57b..e90ec342e 100644
--- a/tex/context/interface/mkiv/context-en.xml
+++ b/tex/context/interface/mkiv/context-en.xml
@@ -652,6 +652,9 @@
<cd:parameter name="buffer">
<cd:constant type="cd:buffer"/>
</cd:parameter>
+ <cd:parameter name="type">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
<cd:parameter name="state">
<cd:constant default="yes" type="start"/>
<cd:constant type="stop"/>
@@ -2432,7 +2435,7 @@
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command file="supp-box.mkiv" level="system" name="naturalhbox">
+ <cd:command file="supp-dir.mkiv" level="system" name="naturalhbox">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
<cd:constant type="cd:text"/>
@@ -2440,7 +2443,7 @@
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command file="supp-box.mkiv" level="system" name="naturalvbox">
+ <cd:command file="supp-dir.mkiv" level="system" name="naturalvbox">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
<cd:constant type="cd:text"/>
@@ -2448,7 +2451,7 @@
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command file="supp-box.mkiv" level="system" name="naturalvtop">
+ <cd:command file="supp-dir.mkiv" level="system" name="naturalvtop">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
<cd:constant type="cd:text"/>
@@ -2464,7 +2467,31 @@
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command file="supp-box.mkiv" level="system" name="naturalhpack">
+ <cd:command file="supp-dir.mkiv" level="system" name="naturalhpack">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command file="supp-dir.mkiv" level="system" name="naturalvpack">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command file="supp-dir.mkiv" level="system" name="naturaltpack">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command file="supp-dir.mkiv" level="system" name="reversehbox">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
<cd:constant type="cd:text"/>
@@ -2472,7 +2499,39 @@
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command file="supp-box.mkiv" level="system" name="naturalvpack">
+ <cd:command file="supp-dir.mkiv" level="system" name="reversevbox">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command file="supp-dir.mkiv" level="system" name="reversevtop">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command file="supp-dir.mkiv" level="system" name="reversehpack">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command file="supp-dir.mkiv" level="system" name="reversevpack">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command file="supp-dir.mkiv" level="system" name="reversetpack">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
<cd:constant type="cd:text"/>
@@ -2711,6 +2770,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="alignment" file="spac-ali.mkiv" level="system" name="rtlhbox">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="alignment" file="spac-ali.mkiv" level="system" name="lefttorighthbox">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
@@ -2719,6 +2786,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="alignment" file="spac-ali.mkiv" level="system" name="ltrhbox">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="alignment" file="spac-ali.mkiv" level="system" name="righttoleftvbox">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
@@ -2727,6 +2802,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="alignment" file="spac-ali.mkiv" level="system" name="rtlvbox">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="alignment" file="spac-ali.mkiv" level="system" name="lefttorightvbox">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
@@ -2735,6 +2818,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="alignment" file="spac-ali.mkiv" level="system" name="ltrvbox">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="alignment" file="spac-ali.mkiv" level="system" name="righttoleftvtop">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
@@ -2743,6 +2834,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="alignment" file="spac-ali.mkiv" level="system" name="rtlvtop">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="alignment" file="spac-ali.mkiv" level="system" name="lefttorightvtop">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
@@ -2751,6 +2850,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="alignment" file="spac-ali.mkiv" level="system" name="ltrvtop">
+ <cd:arguments>
+ <cd:keywords delimiters="none" optional="yes">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="alignment" file="spac-ali.mkiv" level="system" name="autodirhbox">
<cd:arguments>
<cd:keywords delimiters="none" optional="yes">
@@ -3574,6 +3681,13 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="fonts" file="typo-cap.mkiv" level="style" name="cap">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
<cd:command category="fonts" file="typo-cap.mkiv" level="style" name="mixedcaps">
<cd:arguments>
<cd:keywords delimiters="braces">
@@ -3595,6 +3709,20 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="fonts" file="typo-cap.mkiv" level="style" name="capital">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="fonts" file="typo-cap.mkiv" level="style" name="smallcaps">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
<cd:command category="fonts" file="typo-cap.mkiv" level="style" name="uppercased">
<cd:arguments>
<cd:keywords delimiters="braces">
@@ -5190,106 +5318,6 @@
</cd:arguments>
</cd:command>
</cd:interface>
- <cd:interface file="i-columns.xml">
- <cd:command category="columns" file="page-mul.mkiv" level="style" name="setupcolumns">
- <cd:arguments>
- <cd:assignments list="yes">
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="distance">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="option">
- <cd:constant type="background"/>
- </cd:parameter>
- <cd:parameter name="offset">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="command">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="height">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="direction">
- <cd:constant type="left"/>
- <cd:constant default="yes" type="right"/>
- </cd:parameter>
- <cd:parameter name="balance">
- <cd:constant default="yes" type="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="align">
- <cd:inherit type="setupalign"/>
- </cd:parameter>
- <cd:parameter name="tolerance">
- <cd:inherit type="setuptolerance"/>
- </cd:parameter>
- <cd:parameter name="blank">
- <cd:inherit name="blank"/>
- </cd:parameter>
- <cd:parameter name="ntop">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="rule">
- <cd:constant type="on"/>
- <cd:constant default="yes" type="off"/>
- <cd:constant type="cd:command"/>
- </cd:parameter>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
- <cd:command category="columns" file="page-mul.mkiv" level="document" name="columns" type="environment">
- <cd:arguments>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupcolumns"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
- <cd:command category="columns" file="page-mul.mkiv" level="style" name="setupcolumnspan">
- <cd:arguments>
- <cd:assignments list="yes">
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:inherit name="setupframed"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
- <cd:command category="columns" file="page-mul.mkiv" level="document" name="columnspan" type="environment">
- <cd:arguments>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupcolumnspan"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
- <cd:command category="columns" file="page-mul.mkiv" level="system" name="setsimplecolumnhsize">
- <cd:arguments>
- <cd:assignments list="yes">
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="width">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="distance">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="lines">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
- <cd:command category="columns" file="page-mul.mkiv" level="system" name="simplecolumns" type="environment">
- <cd:arguments>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setsimplecolumnhsize"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
- </cd:interface>
<cd:interface file="i-combination.xml">
<cd:command category="tables" file="pack-com.mkiv" level="style" name="definecombination">
<cd:arguments>
@@ -6336,7 +6364,7 @@
</cd:command>
<cd:command category="counter language" file="core-con.mkiv" level="document" name="date">
<cd:arguments>
- <cd:assignments list="yes" optional="yes">
+ <cd:assignments list="yes">
<cd:parameter name="d">
<cd:constant type="cd:number"/>
</cd:parameter>
@@ -6493,6 +6521,7 @@
<cd:constant type="set␣2"/>
<cd:constant type="set␣3"/>
<cd:constant type="continued"/>
+ <cd:constant type="zero"/>
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:keywords delimiters="braces">
@@ -6673,6 +6702,13 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="counter" file="core-con.mkiv" level="style" name="zeronumberconversion">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:number"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
</cd:interface>
<cd:interface file="i-counter.xml">
<cd:command category="counter" file="strc-num.mkiv" level="system" name="definecounter">
@@ -7857,22 +7893,6 @@
</cd:command>
<cd:command category="language alignment" file="typo-dir.mkiv" level="style" name="resetdirection"/>
<cd:command category="alignment" file="supp-dir.mkiv" level="document" name="showdirsinmargin"/>
- <cd:command category="alignment" file="supp-dir.mkiv" level="system" name="istltdir">
- <cd:arguments>
- <cd:keywords delimiters="none">
- <cd:constant type="TLT"/>
- <cd:constant type="TRT"/>
- </cd:keywords>
- </cd:arguments>
- </cd:command>
- <cd:command category="alignment" file="supp-dir.mkiv" level="system" name="istrtdir">
- <cd:arguments>
- <cd:keywords delimiters="none">
- <cd:constant type="TLT"/>
- <cd:constant type="TRT"/>
- </cd:keywords>
- </cd:arguments>
- </cd:command>
</cd:interface>
<cd:interface file="i-document.xml">
<cd:command category="structure" file="file-job.mkvi" level="document" name="text" type="environment"/>
@@ -10068,14 +10088,50 @@
<cd:command category="background layout" file="page-app.mkiv" level="style" name="setupTEXpage">
<cd:arguments>
<cd:assignments list="yes">
- <cd:inherit name="setupfittingpage"/>
+ <cd:parameter name="pagestate">
+ <cd:constant type="start"/>
+ <cd:constant default="yes" type="stop"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="margin">
+ <cd:constant type="page"/>
+ </cd:parameter>
+ <cd:parameter name="scale">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="paper">
+ <cd:constant type="auto"/>
+ <cd:constant default="yes" type="default"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:inherit name="setupframed"/>
</cd:assignments>
</cd:arguments>
</cd:command>
<cd:command category="background layout metapost" file="meta-fig.mkiv" level="style" name="setupMPpage">
<cd:arguments>
<cd:assignments list="yes">
- <cd:inherit name="setupfittingpage"/>
+ <cd:parameter name="pagestate">
+ <cd:constant type="start"/>
+ <cd:constant default="yes" type="stop"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="margin">
+ <cd:constant type="page"/>
+ </cd:parameter>
+ <cd:parameter name="scale">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="paper">
+ <cd:constant type="auto"/>
+ <cd:constant default="yes" type="default"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:inherit name="setupframed"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -10542,6 +10598,17 @@
<cd:constant type="effective"/>
<cd:constant type="header"/>
<cd:constant type="footer"/>
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
</cd:keywords>
<cd:keywords list="yes" optional="yes">
<cd:constant type="cd:reference"/>
@@ -10620,6 +10687,17 @@
<cd:constant type="effective"/>
<cd:constant type="header"/>
<cd:constant type="footer"/>
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
</cd:keywords>
<cd:keywords list="yes" optional="yes">
<cd:constant type="cd:reference"/>
@@ -10705,6 +10783,17 @@
<cd:constant type="effective"/>
<cd:constant type="header"/>
<cd:constant type="footer"/>
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
</cd:parameter>
<cd:parameter name="reference">
<cd:constant type="cd:reference"/>
@@ -10798,6 +10887,17 @@
<cd:constant type="effective"/>
<cd:constant type="header"/>
<cd:constant type="footer"/>
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
</cd:parameter>
<cd:parameter name="reference">
<cd:constant type="cd:reference"/>
@@ -10872,6 +10972,17 @@
<cd:constant type="effective"/>
<cd:constant type="header"/>
<cd:constant type="footer"/>
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
</cd:keywords>
<cd:keywords list="yes" optional="yes">
<cd:constant type="cd:reference"/>
@@ -11130,6 +11241,17 @@
<cd:constant type="effective"/>
<cd:constant type="header"/>
<cd:constant type="footer"/>
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
</cd:keywords>
<cd:keywords list="yes" optional="yes">
<cd:constant type="cd:reference"/>
@@ -14622,7 +14744,7 @@
<cd:constant type="frame"/>
<cd:constant type="empty"/>
</cd:parameter>
- <cd:parameter name="forgroundcolor">
+ <cd:parameter name="foregroundcolor">
<cd:constant type="cd:color"/>
</cd:parameter>
<cd:parameter name="reset">
@@ -16825,6 +16947,8 @@
<cd:constant type="attachment"/>
<cd:constant type="layer"/>
<cd:constant type="title"/>
+ <cd:constant type="lefttoright"/>
+ <cd:constant type="righttoleft"/>
<cd:constant type="nomenubar"/>
</cd:parameter>
<cd:parameter name="copies">
@@ -17808,6 +17932,18 @@
<cd:constant type="standard"/>
<cd:constant type="cd:dimension"/>
</cd:parameter>
+ <cd:parameter name="leftmargindistance">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargindistance">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
<cd:parameter name="align">
<cd:inherit name="setupalign"/>
</cd:parameter>
@@ -17915,7 +18051,214 @@
<cd:constant method="range" prefix="cd:name" type="cd:number"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setupitemgroup"/>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="inbetween">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="beforehead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="afterhead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="lefttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="righttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="left">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="right">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="factor">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="step">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="option">
+ <cd:constant type="intro"/>
+ <cd:constant type="random"/>
+ <cd:constant type="continue"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="autointro"/>
+ <cd:constant type="broad"/>
+ <cd:constant type="text"/>
+ <cd:constant type="before"/>
+ <cd:constant type="after"/>
+ <cd:constant type="nowhite"/>
+ <cd:constant type="margin"/>
+ <cd:constant type="inmargin"/>
+ <cd:constant type="atmargin"/>
+ <cd:constant type="intext"/>
+ <cd:constant type="loose"/>
+ <cd:constant type="fit"/>
+ <cd:constant type="nofit"/>
+ <cd:constant type="paragraph"/>
+ <cd:constant type="joinedup"/>
+ <cd:constant type="serried"/>
+ <cd:constant type="stopper"/>
+ <cd:constant type="unpacked"/>
+ <cd:constant type="repeat"/>
+ <cd:constant type="norepeat"/>
+ <cd:constant type="reverse"/>
+ <cd:constant type="columns"/>
+ <cd:constant type="one"/>
+ <cd:constant type="two"/>
+ <cd:constant type="three"/>
+ <cd:constant type="four"/>
+ <cd:constant type="five"/>
+ <cd:constant type="six"/>
+ <cd:constant type="seven"/>
+ <cd:constant type="eight"/>
+ <cd:constant type="nine"/>
+ <cd:constant type="standard"/>
+ <cd:constant method="factor" prefix="cd:number" type="broad"/>
+ <cd:constant method="factor" prefix="cd:number" type="serried"/>
+ <cd:constant type="horizontal"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="margin">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargin">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargin">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargindistance">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargindistance">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="indenting">
+ <cd:inherit name="setupindenting"/>
+ </cd:parameter>
+ <cd:parameter name="start">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="symalign">
+ <cd:constant type="left"/>
+ <cd:constant type="middle"/>
+ <cd:constant type="right"/>
+ <cd:constant type="flushleft"/>
+ <cd:constant type="center"/>
+ <cd:constant type="flushright"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="indentnext">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="auto"/>
+ </cd:parameter>
+ <cd:parameter name="inner">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:csname"/>
+ </cd:parameter>
+ <cd:parameter name="items">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="itemalign">
+ <cd:constant type="left"/>
+ <cd:constant type="right"/>
+ <cd:constant type="middle"/>
+ <cd:constant type="flushleft"/>
+ <cd:constant type="flushright"/>
+ <cd:constant type="inner"/>
+ <cd:constant type="outer"/>
+ </cd:parameter>
+ <cd:parameter name="alignsymbol">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ </cd:parameter>
+ <cd:parameter name="textdistance">
+ <cd:constant type="small"/>
+ <cd:constant type="medium"/>
+ <cd:constant type="big"/>
+ <cd:constant type="none"/>
+ <cd:constant default="yes" type="space"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="placestopper">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="headstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="headcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="marstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="marcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="symstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="symcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="grid">
+ <cd:inherit name="definegridsnapping"/>
+ </cd:parameter>
+ <cd:inherit name="setupcounter"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -17930,10 +18273,215 @@
<cd:constant type="cd:number"/>
</cd:keywords>
<cd:keywords list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
+ <cd:constant type="intro"/>
+ <cd:constant type="random"/>
+ <cd:constant type="continue"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="autointro"/>
+ <cd:constant type="broad"/>
+ <cd:constant type="text"/>
+ <cd:constant type="before"/>
+ <cd:constant type="after"/>
+ <cd:constant type="nowhite"/>
+ <cd:constant type="margin"/>
+ <cd:constant type="inmargin"/>
+ <cd:constant type="atmargin"/>
+ <cd:constant type="intext"/>
+ <cd:constant type="loose"/>
+ <cd:constant type="fit"/>
+ <cd:constant type="nofit"/>
+ <cd:constant type="paragraph"/>
+ <cd:constant type="joinedup"/>
+ <cd:constant type="serried"/>
+ <cd:constant type="stopper"/>
+ <cd:constant type="nostopper"/>
+ <cd:constant type="unpacked"/>
+ <cd:constant type="repeat"/>
+ <cd:constant type="norepeat"/>
+ <cd:constant type="reverse"/>
+ <cd:constant type="columns"/>
+ <cd:constant type="one"/>
+ <cd:constant type="two"/>
+ <cd:constant type="three"/>
+ <cd:constant type="four"/>
+ <cd:constant type="five"/>
+ <cd:constant type="six"/>
+ <cd:constant type="seven"/>
+ <cd:constant type="eight"/>
+ <cd:constant type="nine"/>
+ <cd:constant type="standard"/>
+ <cd:constant method="factor" prefix="cd:number" type="broad"/>
+ <cd:constant method="factor" prefix="cd:number" type="serried"/>
+ <cd:constant type="horizontal"/>
+ <cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="inbetween">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="beforehead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="afterhead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="lefttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="righttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="left">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="right">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="factor">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="step">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="margin">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargin">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargin">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargindistance">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargindistance">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="indenting">
+ <cd:inherit name="setupindenting"/>
+ </cd:parameter>
+ <cd:parameter name="start">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="symalign">
+ <cd:constant type="left"/>
+ <cd:constant type="middle"/>
+ <cd:constant type="right"/>
+ <cd:constant type="flushleft"/>
+ <cd:constant type="center"/>
+ <cd:constant type="flushright"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="indentnext">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ <cd:constant type="auto"/>
+ </cd:parameter>
+ <cd:parameter name="inner">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:csname"/>
+ </cd:parameter>
+ <cd:parameter name="items">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="itemalign">
+ <cd:constant type="left"/>
+ <cd:constant type="right"/>
+ <cd:constant type="middle"/>
+ <cd:constant type="flushleft"/>
+ <cd:constant type="flushright"/>
+ <cd:constant type="inner"/>
+ <cd:constant type="outer"/>
+ </cd:parameter>
+ <cd:parameter name="alignsymbol">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ </cd:parameter>
+ <cd:parameter name="textdistance">
+ <cd:constant type="small"/>
+ <cd:constant type="medium"/>
+ <cd:constant type="big"/>
+ <cd:constant type="none"/>
+ <cd:constant default="yes" type="space"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="placestopper">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="headstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="headcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="marstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="marcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="symstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="symcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="grid">
+ <cd:inherit name="definegridsnapping"/>
+ </cd:parameter>
+ <cd:inherit name="setupcounter"/>
</cd:assignments>
</cd:arguments>
<cd:instances>
@@ -22304,6 +22852,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="mathematics" file="math-ini.mkiv" level="document" name="mathematics" variant="assignment">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setupmathematics"/>
+ </cd:assignments>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="mathematics" file="math-ini.mkiv" level="document" name="math">
<cd:arguments>
<cd:keywords optional="yes">
@@ -22312,6 +22868,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="mathematics" file="math-ini.mkiv" level="document" name="math" variant="assignment">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setupmathematics"/>
+ </cd:assignments>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="mathematics" file="math-ini.mkiv" level="document" name="m">
<cd:arguments>
<cd:keywords optional="yes">
@@ -22320,6 +22884,14 @@
<cd:content/>
</cd:arguments>
</cd:command>
+ <cd:command category="mathematics" file="math-ini.mkiv" level="document" name="m" variant="assignment">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setupmathematics"/>
+ </cd:assignments>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
<cd:command category="mathematics" file="math-ini.mkiv" level="style" name="definemathcommand">
<cd:arguments>
<cd:keywords>
@@ -22715,6 +23287,8 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="mathematics" file="math-ini.mkiv" level="document" name="stackscripts"/>
+ <cd:command category="mathematics" file="math-ini.mkiv" level="document" name="unstackscripts"/>
</cd:interface>
<cd:interface file="i-mathalignment.xml">
<cd:command category="mathematics alignment" file="math-ali.mkiv" level="style" name="definemathalignment">
@@ -22922,6 +23496,38 @@
<cd:command category="mathematics" file="math-fen.mkiv" level="document" name="fenced">
<cd:arguments>
<cd:keywords>
+ <cd:constant type="parenthesis"/>
+ <cd:constant type="bracket"/>
+ <cd:constant type="brace"/>
+ <cd:constant type="bar"/>
+ <cd:constant type="doublebar"/>
+ <cd:constant type="triplebar"/>
+ <cd:constant type="angle"/>
+ <cd:constant type="doubleangle"/>
+ <cd:constant type="solidus"/>
+ <cd:constant type="ceiling"/>
+ <cd:constant type="floor"/>
+ <cd:constant type="moustache"/>
+ <cd:constant type="uppercorner"/>
+ <cd:constant type="lowercorner"/>
+ <cd:constant type="group"/>
+ <cd:constant type="openbracket"/>
+ <cd:constant type="mirroredparenthesis"/>
+ <cd:constant type="mirroredbracket"/>
+ <cd:constant type="mirroredbrace"/>
+ <cd:constant type="mirroredbar"/>
+ <cd:constant type="mirroreddoublebar"/>
+ <cd:constant type="mirroredtriplebar"/>
+ <cd:constant type="mirroredangle"/>
+ <cd:constant type="mirroreddoubleangle"/>
+ <cd:constant type="mirroredsolidus"/>
+ <cd:constant type="mirroredceiling"/>
+ <cd:constant type="mirroredfloor"/>
+ <cd:constant type="mirroredmoustache"/>
+ <cd:constant type="mirroreduppercorner"/>
+ <cd:constant type="mirroredlowercorner"/>
+ <cd:constant type="mirroredgroup"/>
+ <cd:constant type="mirroredopenbracket"/>
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:content/>
@@ -22931,6 +23537,56 @@
<cd:command category="mathematics" file="math-fen.mkiv" level="document" name="left">
<cd:arguments>
<cd:keywords delimiters="none">
+ <cd:constant type="\\\\\\\\bgroup"/>
+ <cd:constant type="\\\\\\\\egroup"/>
+ <cd:constant type="\\\\\\\\letteropenbrace"/>
+ <cd:constant type="["/>
+ <cd:constant type="]"/>
+ <cd:constant type="("/>
+ <cd:constant type=")"/>
+ <cd:constant type="&lt;"/>
+ <cd:constant type="&gt;"/>
+ <cd:constant type="/"/>
+ <cd:constant type="|"/>
+ <cd:constant type="⌊"/>
+ <cd:constant type="⌋"/>
+ <cd:constant type="⌈"/>
+ <cd:constant type="⌉"/>
+ <cd:constant type="⟨"/>
+ <cd:constant type="⟩"/>
+ <cd:constant type="⟪"/>
+ <cd:constant type="⟫"/>
+ <cd:constant type="‖"/>
+ <cd:constant type="⦀"/>
+ <cd:constant type="⦗"/>
+ <cd:constant type="\\\\\\\\lbrace"/>
+ <cd:constant type="\\\\\\\\lbracket"/>
+ <cd:constant type="\\\\\\\\lbrack"/>
+ <cd:constant type="\\\\\\\\lparenthesis"/>
+ <cd:constant type="\\\\\\\\lparent"/>
+ <cd:constant type="\\\\\\\\lparen"/>
+ <cd:constant type="\\\\\\\\langle"/>
+ <cd:constant type="\\\\\\\\llangle"/>
+ <cd:constant type="\\\\\\\\lVert"/>
+ <cd:constant type="\\\\\\\\vert"/>
+ <cd:constant type="\\\\\\\\solidus"/>
+ <cd:constant type="\\\\\\\\lfloor"/>
+ <cd:constant type="\\\\\\\\lceiling"/>
+ <cd:constant type="\\\\\\\\lceil"/>
+ <cd:constant type="\\\\\\\\ulcorner"/>
+ <cd:constant type="\\\\\\\\llcorner"/>
+ <cd:constant type="\\\\\\\\lmoustache"/>
+ <cd:constant type="\\\\\\\\llbracket"/>
+ <cd:constant type="\\\\\\\\lgroup"/>
+ <cd:constant type="\\\\\\\\linterval"/>
+ <cd:constant type="\\\\\\\\lointerval"/>
+ <cd:constant type="\\\\\\\\llointerval"/>
+ <cd:constant type="\\\\\\\\lrointerval"/>
+ <cd:constant type="\\\\\\\\{"/>
+ <cd:constant type="\\\\\\\\["/>
+ <cd:constant type="\\\\\\\\("/>
+ <cd:constant type="\\\\\\\\&lt;"/>
+ <cd:constant type="\\\\\\\\|"/>
<cd:constant type="cd:character"/>
</cd:keywords>
</cd:arguments>
@@ -22945,6 +23601,56 @@
<cd:command category="mathematics" file="math-fen.mkiv" level="document" name="right">
<cd:arguments>
<cd:keywords delimiters="none">
+ <cd:constant type="\\\\\\\\egroup"/>
+ <cd:constant type="\\\\\\\\bgroup"/>
+ <cd:constant type="\\\\\\\\letterclosebrace"/>
+ <cd:constant type="]"/>
+ <cd:constant type="["/>
+ <cd:constant type=")"/>
+ <cd:constant type="("/>
+ <cd:constant type="&gt;"/>
+ <cd:constant type="&lt;"/>
+ <cd:constant type="/"/>
+ <cd:constant type="|"/>
+ <cd:constant type="⌋"/>
+ <cd:constant type="⌊"/>
+ <cd:constant type="⌉"/>
+ <cd:constant type="⌈"/>
+ <cd:constant type="⟩"/>
+ <cd:constant type="⟨"/>
+ <cd:constant type="⟫"/>
+ <cd:constant type="⟪"/>
+ <cd:constant type="‖"/>
+ <cd:constant type="⦀"/>
+ <cd:constant type="⦘"/>
+ <cd:constant type="\\\\\\\\rbrace"/>
+ <cd:constant type="\\\\\\\\rbracket"/>
+ <cd:constant type="\\\\\\\\rbracket"/>
+ <cd:constant type="\\\\\\\\rparenthesis"/>
+ <cd:constant type="\\\\\\\\rparent"/>
+ <cd:constant type="\\\\\\\\rparen"/>
+ <cd:constant type="\\\\\\\\rangle"/>
+ <cd:constant type="\\\\\\\\rrangle"/>
+ <cd:constant type="\\\\\\\\rVert"/>
+ <cd:constant type="\\\\\\\\vert"/>
+ <cd:constant type="\\\\\\\\solidus"/>
+ <cd:constant type="\\\\\\\\rfloor"/>
+ <cd:constant type="\\\\\\\\rceiling"/>
+ <cd:constant type="\\\\\\\\rceil"/>
+ <cd:constant type="\\\\\\\\urcorner"/>
+ <cd:constant type="\\\\\\\\lrcorner"/>
+ <cd:constant type="\\\\\\\\rmoustache"/>
+ <cd:constant type="\\\\\\\\rrbracket"/>
+ <cd:constant type="\\\\\\\\rgroup"/>
+ <cd:constant type="\\\\\\\\rinterval"/>
+ <cd:constant type="\\\\\\\\rointerval"/>
+ <cd:constant type="\\\\\\\\rlointerval"/>
+ <cd:constant type="\\\\\\\\rrointerval"/>
+ <cd:constant type="\\\\\\\\}"/>
+ <cd:constant type="\\\\\\\\]"/>
+ <cd:constant type="\\\\\\\\)"/>
+ <cd:constant type="\\\\\\\\&gt;"/>
+ <cd:constant type="\\\\\\\\|"/>
<cd:constant type="cd:character"/>
</cd:keywords>
</cd:arguments>
@@ -23064,6 +23770,56 @@
<cd:command category="mathematics" file="math-fen.mkiv" level="document" name="lfence">
<cd:arguments>
<cd:keywords delimiters="braces">
+ <cd:constant type="\\\\\\\\bgroup"/>
+ <cd:constant type="\\\\\\\\egroup"/>
+ <cd:constant type="\\\\\\\\letteropenbrace"/>
+ <cd:constant type="["/>
+ <cd:constant type="]"/>
+ <cd:constant type="("/>
+ <cd:constant type=")"/>
+ <cd:constant type="&lt;"/>
+ <cd:constant type="&gt;"/>
+ <cd:constant type="/"/>
+ <cd:constant type="|"/>
+ <cd:constant type="⌊"/>
+ <cd:constant type="⌋"/>
+ <cd:constant type="⌈"/>
+ <cd:constant type="⌉"/>
+ <cd:constant type="⟨"/>
+ <cd:constant type="⟩"/>
+ <cd:constant type="⟪"/>
+ <cd:constant type="⟫"/>
+ <cd:constant type="‖"/>
+ <cd:constant type="⦀"/>
+ <cd:constant type="⦗"/>
+ <cd:constant type="\\\\\\\\lbrace"/>
+ <cd:constant type="\\\\\\\\lbracket"/>
+ <cd:constant type="\\\\\\\\lbrack"/>
+ <cd:constant type="\\\\\\\\lparenthesis"/>
+ <cd:constant type="\\\\\\\\lparent"/>
+ <cd:constant type="\\\\\\\\lparen"/>
+ <cd:constant type="\\\\\\\\langle"/>
+ <cd:constant type="\\\\\\\\llangle"/>
+ <cd:constant type="\\\\\\\\lVert"/>
+ <cd:constant type="\\\\\\\\vert"/>
+ <cd:constant type="\\\\\\\\solidus"/>
+ <cd:constant type="\\\\\\\\lfloor"/>
+ <cd:constant type="\\\\\\\\lceiling"/>
+ <cd:constant type="\\\\\\\\lceil"/>
+ <cd:constant type="\\\\\\\\ulcorner"/>
+ <cd:constant type="\\\\\\\\llcorner"/>
+ <cd:constant type="\\\\\\\\lmoustache"/>
+ <cd:constant type="\\\\\\\\llbracket"/>
+ <cd:constant type="\\\\\\\\lgroup"/>
+ <cd:constant type="\\\\\\\\linterval"/>
+ <cd:constant type="\\\\\\\\lointerval"/>
+ <cd:constant type="\\\\\\\\llointerval"/>
+ <cd:constant type="\\\\\\\\lrointerval"/>
+ <cd:constant type="\\\\\\\\{"/>
+ <cd:constant type="\\\\\\\\["/>
+ <cd:constant type="\\\\\\\\("/>
+ <cd:constant type="\\\\\\\\&lt;"/>
+ <cd:constant type="\\\\\\\\|"/>
<cd:constant type="cd:character"/>
</cd:keywords>
</cd:arguments>
@@ -23078,6 +23834,56 @@
<cd:command category="mathematics" file="math-fen.mkiv" level="document" name="rfence">
<cd:arguments>
<cd:keywords delimiters="braces">
+ <cd:constant type="\\\\\\\\egroup"/>
+ <cd:constant type="\\\\\\\\bgroup"/>
+ <cd:constant type="\\\\\\\\letterclosebrace"/>
+ <cd:constant type="]"/>
+ <cd:constant type="["/>
+ <cd:constant type=")"/>
+ <cd:constant type="("/>
+ <cd:constant type="&gt;"/>
+ <cd:constant type="&lt;"/>
+ <cd:constant type="/"/>
+ <cd:constant type="|"/>
+ <cd:constant type="⌋"/>
+ <cd:constant type="⌊"/>
+ <cd:constant type="⌉"/>
+ <cd:constant type="⌈"/>
+ <cd:constant type="⟩"/>
+ <cd:constant type="⟨"/>
+ <cd:constant type="⟫"/>
+ <cd:constant type="⟪"/>
+ <cd:constant type="‖"/>
+ <cd:constant type="⦀"/>
+ <cd:constant type="⦘"/>
+ <cd:constant type="\\\\\\\\rbrace"/>
+ <cd:constant type="\\\\\\\\rbracket"/>
+ <cd:constant type="\\\\\\\\rbracket"/>
+ <cd:constant type="\\\\\\\\rparenthesis"/>
+ <cd:constant type="\\\\\\\\rparent"/>
+ <cd:constant type="\\\\\\\\rparen"/>
+ <cd:constant type="\\\\\\\\rangle"/>
+ <cd:constant type="\\\\\\\\rrangle"/>
+ <cd:constant type="\\\\\\\\rVert"/>
+ <cd:constant type="\\\\\\\\vert"/>
+ <cd:constant type="\\\\\\\\solidus"/>
+ <cd:constant type="\\\\\\\\rfloor"/>
+ <cd:constant type="\\\\\\\\rceiling"/>
+ <cd:constant type="\\\\\\\\rceil"/>
+ <cd:constant type="\\\\\\\\urcorner"/>
+ <cd:constant type="\\\\\\\\lrcorner"/>
+ <cd:constant type="\\\\\\\\rmoustache"/>
+ <cd:constant type="\\\\\\\\rrbracket"/>
+ <cd:constant type="\\\\\\\\rgroup"/>
+ <cd:constant type="\\\\\\\\rinterval"/>
+ <cd:constant type="\\\\\\\\rointerval"/>
+ <cd:constant type="\\\\\\\\rlointerval"/>
+ <cd:constant type="\\\\\\\\rrointerval"/>
+ <cd:constant type="\\\\\\\\}"/>
+ <cd:constant type="\\\\\\\\]"/>
+ <cd:constant type="\\\\\\\\)"/>
+ <cd:constant type="\\\\\\\\&gt;"/>
+ <cd:constant type="\\\\\\\\|"/>
<cd:constant type="cd:character"/>
</cd:keywords>
</cd:arguments>
@@ -24446,8 +25252,16 @@
<cd:instances>
<cd:constant value="itemgroupcolumns"/>
<cd:constant value="boxedcolumns"/>
+ <cd:constant value="columns"/>
</cd:instances>
</cd:command>
+ <cd:command category="structure layout" file="page-smp.mkiv" level="style" name="setupcolumns">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:inherit name="setupmixedcolumns"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
</cd:interface>
<cd:interface file="i-modes.xml">
<cd:command category="structure" file="core-env.mkiv" level="system" name="newmode">
@@ -25678,6 +26492,13 @@
</cd:assignments>
</cd:arguments>
</cd:command>
+ <cd:command category="structure notes" file="strc-not.mkvi" level="style" name="setupfootnotes">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:inherit name="setupnote"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
<cd:command category="structure notes" file="strc-not.mkvi" level="document" name="setnote">
<cd:arguments>
<cd:keywords>
@@ -25974,6 +26795,54 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="structure notes" file="strc-tnt.mkiv" level="style" name="definetextnote">
+ <cd:arguments>
+ <cd:keywords>
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
+ <cd:keywords optional="yes">
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setuptextnote"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="structure notes" file="strc-tnt.mkiv" level="style" name="setuptextnote">
+ <cd:arguments>
+ <cd:keywords list="yes" optional="yes">
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
+ <cd:assignments list="yes">
+ <cd:parameter name="rule">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="note">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="*"/>
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="empty">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ <cd:constant type="none"/>
+ <cd:constant type="number"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="structure notes" file="strc-tnt.mkiv" generated="yes" level="document" name="textnote">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setuptextnote"/>
+ </cd:assignments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:text"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
</cd:interface>
<cd:interface file="i-object.xml">
<cd:command category="pdf" file="pack-obj.mkiv" level="system" name="ifinobject">
@@ -26925,7 +27794,29 @@
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupcolumnsetspan"/>
+ <cd:parameter name="c">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="r">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="method">
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
+ </cd:parameter>
+ <cd:parameter name="option">
+ <cd:constant default="yes" type="none"/>
+ <cd:constant type="wide"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -27201,7 +28092,17 @@
<cd:command category="counter" file="strc-pag.mkiv" level="style" name="setuppagenumber">
<cd:arguments>
<cd:assignments list="yes">
- <cd:inherit name="setupuserpagenumber"/>
+ <cd:parameter name="viewerprefix">
+ <cd:constant type="cd:text"/>
+ </cd:parameter>
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="none"/>
+ <cd:constant type="keep"/>
+ <cd:constant type="empty"/>
+ </cd:parameter>
+ <cd:inherit name="setupcounter"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -28164,6 +29065,7 @@
<cd:command category="tables" file="tabl-mis.mkiv" level="style" name="setupparagraphs" variant="assignment">
<cd:arguments>
<cd:keywords optional="yes">
+ <cd:constant type="cd:name"/>
<cd:constant method="range" prefix="cd:name" type="cd:number"/>
</cd:keywords>
<cd:assignments list="yes">
@@ -33560,6 +34462,7 @@
<cd:constant default="yes" type="no"/>
<cd:constant type="all"/>
<cd:constant type="packed"/>
+ <cd:constant type="text"/>
</cd:parameter>
<cd:parameter name="check">
<cd:constant default="yes" type="yes"/>
@@ -33774,6 +34677,8 @@
<cd:constant type="yes"/>
<cd:constant default="yes" type="no"/>
<cd:constant type="all"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="text"/>
</cd:parameter>
<cd:parameter name="check">
<cd:constant default="yes" type="yes"/>
@@ -33950,7 +34855,212 @@
<cd:constant type="cd:number"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setupregister"/>
+ <cd:parameter name="referencemethod">
+ <cd:constant type="forward"/>
+ </cd:parameter>
+ <cd:parameter name="expansion">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ <cd:constant type="xml"/>
+ </cd:parameter>
+ <cd:parameter name="ownnumber">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ </cd:parameter>
+ <cd:parameter name="xmlsetup">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="alternative">
+ <cd:constant type="a"/>
+ <cd:constant type="b"/>
+ <cd:constant type="A"/>
+ <cd:constant type="B"/>
+ </cd:parameter>
+ <cd:parameter name="method">
+ <cd:constant type="default"/>
+ <cd:constant type="before"/>
+ <cd:constant type="after"/>
+ <cd:constant type="first"/>
+ <cd:constant type="last"/>
+ <cd:constant type="ch"/>
+ <cd:constant type="mm"/>
+ <cd:constant type="zm"/>
+ <cd:constant type="pm"/>
+ <cd:constant type="mc"/>
+ <cd:constant type="zc"/>
+ <cd:constant type="pc"/>
+ <cd:constant type="uc"/>
+ </cd:parameter>
+ <cd:parameter name="compress">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ <cd:constant type="all"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="text"/>
+ </cd:parameter>
+ <cd:parameter name="check">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="criterium">
+ <cd:constant type="local"/>
+ <cd:constant type="text"/>
+ <cd:constant type="current"/>
+ <cd:constant type="previous"/>
+ <cd:constant default="yes" type="all"/>
+ <cd:constant type="cd:section"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixseparatorset">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstarter">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstopper">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixsegments">
+ <cd:constant type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="*"/>
+ <cd:constant method="range" prefix="cd:number" type="all"/>
+ <cd:constant type="cd:section"/>
+ <cd:constant method="range" prefix="cd:section" type="cd:section"/>
+ <cd:constant method="range" prefix="cd:section" type="*"/>
+ <cd:constant method="range" prefix="cd:section" type="all"/>
+ <cd:constant type="current"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconnector">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefix">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="pageseparatorset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pagestarter">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagestopper">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagesegments">
+ <cd:constant type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="*"/>
+ <cd:constant method="range" prefix="cd:number" type="all"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="indicator">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="textcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="deeptextcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="pagecommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="interaction">
+ <cd:constant type="text"/>
+ <cd:constant default="yes" type="pagenumber"/>
+ </cd:parameter>
+ <cd:parameter name="pagenumber">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="a"/>
+ <cd:constant default="yes" type="n"/>
+ <cd:constant type="none"/>
+ <cd:constant type="1"/>
+ <cd:constant type="2"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="language">
+ <cd:constant type="default"/>
+ <cd:constant type="DIN␣5007-1"/>
+ <cd:constant type="DIN␣5007-2"/>
+ <cd:constant type="Duden"/>
+ <cd:constant type="de-DE"/>
+ <cd:constant type="de-CH"/>
+ <cd:constant type="de-AT"/>
+ <cd:constant type="ru-iso9"/>
+ <cd:constant type="ocs-scn"/>
+ <cd:constant type="cd:language"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="textstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="textcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pagestyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagecolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pageleft">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageright">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="balance">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="numberorder">
+ <cd:constant default="yes" type="numbers"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -33961,7 +35071,212 @@
<cd:constant method="range" prefix="cd:name" type="cd:number"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setupregister"/>
+ <cd:parameter name="referencemethod">
+ <cd:constant type="forward"/>
+ </cd:parameter>
+ <cd:parameter name="expansion">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ <cd:constant type="xml"/>
+ </cd:parameter>
+ <cd:parameter name="ownnumber">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ </cd:parameter>
+ <cd:parameter name="xmlsetup">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="alternative">
+ <cd:constant type="a"/>
+ <cd:constant type="b"/>
+ <cd:constant type="A"/>
+ <cd:constant type="B"/>
+ </cd:parameter>
+ <cd:parameter name="method">
+ <cd:constant type="default"/>
+ <cd:constant type="before"/>
+ <cd:constant type="after"/>
+ <cd:constant type="first"/>
+ <cd:constant type="last"/>
+ <cd:constant type="ch"/>
+ <cd:constant type="mm"/>
+ <cd:constant type="zm"/>
+ <cd:constant type="pm"/>
+ <cd:constant type="mc"/>
+ <cd:constant type="zc"/>
+ <cd:constant type="pc"/>
+ <cd:constant type="uc"/>
+ </cd:parameter>
+ <cd:parameter name="compress">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ <cd:constant type="all"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="text"/>
+ </cd:parameter>
+ <cd:parameter name="check">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="criterium">
+ <cd:constant type="local"/>
+ <cd:constant type="text"/>
+ <cd:constant type="current"/>
+ <cd:constant type="previous"/>
+ <cd:constant default="yes" type="all"/>
+ <cd:constant type="cd:section"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixseparatorset">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstarter">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstopper">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixsegments">
+ <cd:constant type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="*"/>
+ <cd:constant method="range" prefix="cd:number" type="all"/>
+ <cd:constant type="cd:section"/>
+ <cd:constant method="range" prefix="cd:section" type="cd:section"/>
+ <cd:constant method="range" prefix="cd:section" type="*"/>
+ <cd:constant method="range" prefix="cd:section" type="all"/>
+ <cd:constant type="current"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconnector">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefix">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="pageseparatorset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pagestarter">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagestopper">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagesegments">
+ <cd:constant type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="*"/>
+ <cd:constant method="range" prefix="cd:number" type="all"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="indicator">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="textcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="deeptextcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="pagecommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="interaction">
+ <cd:constant type="text"/>
+ <cd:constant default="yes" type="pagenumber"/>
+ </cd:parameter>
+ <cd:parameter name="pagenumber">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="a"/>
+ <cd:constant default="yes" type="n"/>
+ <cd:constant type="none"/>
+ <cd:constant type="1"/>
+ <cd:constant type="2"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="language">
+ <cd:constant type="default"/>
+ <cd:constant type="DIN␣5007-1"/>
+ <cd:constant type="DIN␣5007-2"/>
+ <cd:constant type="Duden"/>
+ <cd:constant type="de-DE"/>
+ <cd:constant type="de-CH"/>
+ <cd:constant type="de-AT"/>
+ <cd:constant type="ru-iso9"/>
+ <cd:constant type="ocs-scn"/>
+ <cd:constant type="cd:language"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="textstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="textcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pagestyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagecolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pageleft">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageright">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="balance">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="numberorder">
+ <cd:constant default="yes" type="numbers"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -34056,7 +35371,212 @@
<cd:constant type="cd:number"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setupregister"/>
+ <cd:parameter name="referencemethod">
+ <cd:constant type="forward"/>
+ </cd:parameter>
+ <cd:parameter name="expansion">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ <cd:constant type="xml"/>
+ </cd:parameter>
+ <cd:parameter name="ownnumber">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ </cd:parameter>
+ <cd:parameter name="xmlsetup">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="alternative">
+ <cd:constant type="a"/>
+ <cd:constant type="b"/>
+ <cd:constant type="A"/>
+ <cd:constant type="B"/>
+ </cd:parameter>
+ <cd:parameter name="method">
+ <cd:constant type="default"/>
+ <cd:constant type="before"/>
+ <cd:constant type="after"/>
+ <cd:constant type="first"/>
+ <cd:constant type="last"/>
+ <cd:constant type="ch"/>
+ <cd:constant type="mm"/>
+ <cd:constant type="zm"/>
+ <cd:constant type="pm"/>
+ <cd:constant type="mc"/>
+ <cd:constant type="zc"/>
+ <cd:constant type="pc"/>
+ <cd:constant type="uc"/>
+ </cd:parameter>
+ <cd:parameter name="compress">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ <cd:constant type="all"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="text"/>
+ </cd:parameter>
+ <cd:parameter name="check">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="criterium">
+ <cd:constant type="local"/>
+ <cd:constant type="text"/>
+ <cd:constant type="current"/>
+ <cd:constant type="previous"/>
+ <cd:constant default="yes" type="all"/>
+ <cd:constant type="cd:section"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixseparatorset">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstarter">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstopper">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixsegments">
+ <cd:constant type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="*"/>
+ <cd:constant method="range" prefix="cd:number" type="all"/>
+ <cd:constant type="cd:section"/>
+ <cd:constant method="range" prefix="cd:section" type="cd:section"/>
+ <cd:constant method="range" prefix="cd:section" type="*"/>
+ <cd:constant method="range" prefix="cd:section" type="all"/>
+ <cd:constant type="current"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconnector">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefix">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="pageseparatorset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pagestarter">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagestopper">
+ <cd:constant type="cd:command"/>
+ <cd:constant method="apply" prefix="cd:processor" type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagesegments">
+ <cd:constant type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="cd:number"/>
+ <cd:constant method="range" prefix="cd:number" type="*"/>
+ <cd:constant method="range" prefix="cd:number" type="all"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="indicator">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="textcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="deeptextcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="pagecommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="interaction">
+ <cd:constant type="text"/>
+ <cd:constant default="yes" type="pagenumber"/>
+ </cd:parameter>
+ <cd:parameter name="pagenumber">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="a"/>
+ <cd:constant default="yes" type="n"/>
+ <cd:constant type="none"/>
+ <cd:constant type="1"/>
+ <cd:constant type="2"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="language">
+ <cd:constant type="default"/>
+ <cd:constant type="DIN␣5007-1"/>
+ <cd:constant type="DIN␣5007-2"/>
+ <cd:constant type="Duden"/>
+ <cd:constant type="de-DE"/>
+ <cd:constant type="de-CH"/>
+ <cd:constant type="de-AT"/>
+ <cd:constant type="ru-iso9"/>
+ <cd:constant type="ocs-scn"/>
+ <cd:constant type="cd:language"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="textstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="textcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pagestyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pagecolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pageleft">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageright">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="balance">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="numberorder">
+ <cd:constant default="yes" type="numbers"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
<cd:instances>
@@ -34079,10 +35599,10 @@
<cd:constant method="apply" prefix="cd:processor" type="cd:text"/>
</cd:keywords>
<cd:index list="yes"/>
- </cd:arguments>
- </cd:command>
- <cd:command category="structure" file="strc-reg.mkiv" level="document" name="stopregister">
- <cd:arguments>
+ <cd:keywords delimiters="none">
+ <cd:constant type="cd:content"/>
+ </cd:keywords>
+ <cd:delimiter name="stopregister"/>
<cd:keywords>
<cd:constant type="cd:name"/>
</cd:keywords>
@@ -34258,10 +35778,10 @@
<cd:constant type="cd:value"/>
</cd:parameter>
</cd:assignments>
- </cd:arguments>
- </cd:command>
- <cd:command category="structure" file="strc-reg.mkiv" level="document" name="stopstructurepageregister">
- <cd:arguments>
+ <cd:keywords delimiters="none">
+ <cd:constant type="cd:content"/>
+ </cd:keywords>
+ <cd:delimiter name="stopstructurepageregister"/>
<cd:keywords>
<cd:constant type="cd:name"/>
</cd:keywords>
@@ -35128,6 +36648,10 @@
<cd:constant type="positive"/>
<cd:constant type="all"/>
</cd:parameter>
+ <cd:parameter name="hidenumber">
+ <cd:constant type="yes"/>
+ <cd:constant default="yes" type="no"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -35321,6 +36845,34 @@
</cd:assignments>
</cd:arguments>
</cd:command>
+ <cd:command category="structure" file="strc-sec.mkiv" level="system" name="placerawheaddata">
+ <cd:arguments>
+ <cd:keywords>
+ <cd:constant type="cd:section"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="structure" file="strc-sec.mkiv" level="system" name="placerawheadtext">
+ <cd:arguments>
+ <cd:keywords>
+ <cd:constant type="cd:section"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="structure" file="strc-sec.mkiv" level="system" name="placerawheadnumber">
+ <cd:arguments>
+ <cd:keywords>
+ <cd:constant type="cd:section"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="structure" file="strc-sec.mkiv" level="document" name="repeathead">
+ <cd:arguments>
+ <cd:keywords>
+ <cd:constant type="cd:section"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
<cd:command category="structure" file="strc-sec.mkiv" level="system" name="definesection">
<cd:arguments>
<cd:keywords>
@@ -36162,6 +37714,33 @@
</cd:arguments>
</cd:command>
</cd:interface>
+ <cd:interface file="i-simplecolumns.xml">
+ <cd:command category="structure layout" file="page-smp.mkiv" level="system" name="setsimplecolumnshsize">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="lines">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="structure layout" file="page-smp.mkiv" level="system" name="simplecolumns" type="environment">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setsimplecolumnshsize"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+ </cd:interface>
<cd:interface file="i-smash.xml">
<cd:command file="supp-box.mkiv" level="system" name="smashbox">
<cd:arguments>
@@ -36986,6 +38565,16 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="symbols" file="symb-ini.mkiv" level="style" name="setupsymbols">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:parameter name="stylealternative">
+ <cd:constant default="yes" type="text"/>
+ <cd:constant type="math"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
</cd:interface>
<cd:interface file="i-synctex.xml">
<cd:command category="pdf" file="cont-run.mkiv" level="system" name="synctexsetfilename">
@@ -43051,7 +44640,59 @@
<cd:constant type="edge"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="empty"/>
+ <cd:constant type="high"/>
+ <cd:constant type="none"/>
+ <cd:constant default="yes" type="normal"/>
+ <cd:constant type="nomarking"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="strut">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="rightstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="rightcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -43063,7 +44704,59 @@
<cd:constant type="edge"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="empty"/>
+ <cd:constant type="high"/>
+ <cd:constant type="none"/>
+ <cd:constant default="yes" type="normal"/>
+ <cd:constant type="nomarking"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="strut">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="rightstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="rightcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -43075,7 +44768,59 @@
<cd:constant type="edge"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="empty"/>
+ <cd:constant type="high"/>
+ <cd:constant type="none"/>
+ <cd:constant default="yes" type="normal"/>
+ <cd:constant type="nomarking"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="strut">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="rightstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="rightcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -43087,7 +44832,59 @@
<cd:constant type="edge"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="empty"/>
+ <cd:constant type="high"/>
+ <cd:constant type="none"/>
+ <cd:constant default="yes" type="normal"/>
+ <cd:constant type="nomarking"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="strut">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="rightstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="rightcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -43099,7 +44896,59 @@
<cd:constant type="edge"/>
</cd:keywords>
<cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="empty"/>
+ <cd:constant type="high"/>
+ <cd:constant type="none"/>
+ <cd:constant default="yes" type="normal"/>
+ <cd:constant type="nomarking"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="strut">
+ <cd:constant default="yes" type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="rightstyle">
+ <cd:constant type="cd:style"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="rightcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -45822,6 +47671,9 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="whitespace" file="typo-wrp.mkiv" level="document" name="crlf"/>
+ <cd:command category="whitespace" file="typo-wrp.mkiv" level="document" name="settestcrlf"/>
+ <cd:command category="whitespace" file="typo-wrp.mkiv" level="document" name="crlfplaceholder"/>
</cd:interface>
<cd:interface file="i-whitespace.xml">
<cd:command category="whitespace" file="spac-ver.mkiv" level="style" name="setupwhitespace">
diff --git a/tex/context/interface/mkiv/i-attachment.xml b/tex/context/interface/mkiv/i-attachment.xml
index 85cf8843b..550cc57ce 100644
--- a/tex/context/interface/mkiv/i-attachment.xml
+++ b/tex/context/interface/mkiv/i-attachment.xml
@@ -36,6 +36,9 @@
<cd:parameter name="buffer">
<cd:constant type="cd:buffer"/>
</cd:parameter>
+ <cd:parameter name="type">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
<cd:parameter name="state">
<cd:constant type="start" default="yes"/>
<cd:constant type="stop"/>
diff --git a/tex/context/interface/mkiv/i-boxes.xml b/tex/context/interface/mkiv/i-boxes.xml
index e89be4fd0..39034e32b 100644
--- a/tex/context/interface/mkiv/i-boxes.xml
+++ b/tex/context/interface/mkiv/i-boxes.xml
@@ -725,21 +725,21 @@
</cd:arguments>
</cd:command>
- <cd:command name="naturalhbox" level="system" file="supp-box.mkiv">
+ <cd:command name="naturalhbox" level="system" file="supp-dir.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command name="naturalvbox" level="system" file="supp-box.mkiv">
+ <cd:command name="naturalvbox" level="system" file="supp-dir.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command name="naturalvtop" level="system" file="supp-box.mkiv">
+ <cd:command name="naturalvtop" level="system" file="supp-dir.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
<cd:content/>
@@ -753,14 +753,63 @@
</cd:arguments>
</cd:command>
- <cd:command name="naturalhpack" level="system" file="supp-box.mkiv">
+ <cd:command name="naturalhpack" level="system" file="supp-dir.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
<cd:content/>
</cd:arguments>
</cd:command>
- <cd:command name="naturalvpack" level="system" file="supp-box.mkiv">
+ <cd:command name="naturalvpack" level="system" file="supp-dir.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="naturaltpack" level="system" file="supp-dir.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="reversehbox" level="system" file="supp-dir.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="reversevbox" level="system" file="supp-dir.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="reversevtop" level="system" file="supp-dir.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="reversehpack" level="system" file="supp-dir.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="reversevpack" level="system" file="supp-dir.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="reversetpack" level="system" file="supp-dir.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
<cd:content/>
@@ -950,6 +999,13 @@
</cd:arguments>
</cd:command>
+ <cd:command name="rtlhbox" level="system" category="alignment" file="spac-ali.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="lefttorighthbox" level="system" category="alignment" file="spac-ali.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
@@ -957,6 +1013,13 @@
</cd:arguments>
</cd:command>
+ <cd:command name="ltrhbox" level="system" category="alignment" file="spac-ali.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="righttoleftvbox" level="system" category="alignment" file="spac-ali.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
@@ -964,6 +1027,13 @@
</cd:arguments>
</cd:command>
+ <cd:command name="rtlvbox" level="system" category="alignment" file="spac-ali.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="lefttorightvbox" level="system" category="alignment" file="spac-ali.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
@@ -971,6 +1041,13 @@
</cd:arguments>
</cd:command>
+ <cd:command name="ltrvbox" level="system" category="alignment" file="spac-ali.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="righttoleftvtop" level="system" category="alignment" file="spac-ali.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
@@ -978,6 +1055,13 @@
</cd:arguments>
</cd:command>
+ <cd:command name="rtlvtop" level="system" category="alignment" file="spac-ali.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="lefttorightvtop" level="system" category="alignment" file="spac-ali.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
@@ -985,6 +1069,13 @@
</cd:arguments>
</cd:command>
+ <cd:command name="ltrvtop" level="system" category="alignment" file="spac-ali.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="autodirhbox" level="system" category="alignment" file="spac-ali.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
diff --git a/tex/context/interface/mkiv/i-capitals.xml b/tex/context/interface/mkiv/i-capitals.xml
index 4cfb4a080..6115b1519 100644
--- a/tex/context/interface/mkiv/i-capitals.xml
+++ b/tex/context/interface/mkiv/i-capitals.xml
@@ -167,6 +167,12 @@
</cd:arguments>
</cd:command>
+ <cd:command name="cap" level="style" category="fonts" file="typo-cap.mkiv">
+ <cd:arguments>
+ <cd:resolve name="argument-text"/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="mixedcaps" level="style" category="fonts" file="typo-cap.mkiv">
<cd:arguments>
<cd:resolve name="argument-text"/>
@@ -185,6 +191,18 @@
</cd:arguments>
</cd:command>
+ <cd:command name="capital" level="style" category="fonts" file="typo-cap.mkiv">
+ <cd:arguments>
+ <cd:resolve name="argument-text"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="smallcaps" level="style" category="fonts" file="typo-cap.mkiv">
+ <cd:arguments>
+ <cd:resolve name="argument-text"/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="uppercased" level="style" category="fonts" file="typo-cap.mkiv">
<cd:arguments>
<cd:resolve name="argument-text"/>
diff --git a/tex/context/interface/mkiv/i-chart.xml b/tex/context/interface/mkiv/i-chart.xml
index 7f0a51393..43672efa0 100644
--- a/tex/context/interface/mkiv/i-chart.xml
+++ b/tex/context/interface/mkiv/i-chart.xml
@@ -541,4 +541,4 @@
</cd:arguments>
</cd:command>
-</cd:interface>
+</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-columns.xml b/tex/context/interface/mkiv/i-columns.xml
index bbc022ac6..aa290a0a9 100644
--- a/tex/context/interface/mkiv/i-columns.xml
+++ b/tex/context/interface/mkiv/i-columns.xml
@@ -34,10 +34,10 @@
<cd:constant type="no"/>
</cd:parameter>
<cd:parameter name="align">
- <cd:inherit type="setupalign"/>
+ <cd:inherit name="setupalign"/>
</cd:parameter>
<cd:parameter name="tolerance">
- <cd:inherit type="setuptolerance"/>
+ <cd:inherit name="setuptolerance"/>
</cd:parameter>
<cd:parameter name="blank">
<cd:inherit name="blank"/>
@@ -81,7 +81,7 @@
</cd:arguments>
</cd:command>
- <cd:command name="setsimplecolumnhsize" level="system" category="columns" file="page-mul.mkiv">
+ <cd:command name="setsimplecolumnshsize" level="system" category="columns" file="page-mul.mkiv">
<cd:arguments>
<cd:assignments list="yes">
<cd:parameter name="n">
@@ -103,9 +103,9 @@
<cd:command name="simplecolumns" type="environment" level="system" category="columns" file="page-mul.mkiv">
<cd:arguments>
<cd:assignments list="yes" optional="yes">
- <cd:inherit name="setsimplecolumnhsize"/>
+ <cd:inherit name="setsimplecolumnshsize"/>
</cd:assignments>
</cd:arguments>
</cd:command>
-</cd:interface>
+</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-common-argument.xml b/tex/context/interface/mkiv/i-common-argument.xml
index de000148b..da821c516 100644
--- a/tex/context/interface/mkiv/i-common-argument.xml
+++ b/tex/context/interface/mkiv/i-common-argument.xml
@@ -524,7 +524,7 @@
<!-- * -->
<!-- \... {...} -->
<!-- -->
- <!-- * TOCHAR -->
+ <!-- * TOCHAR -->
<cd:define name="argument-tochar">
<cd:keywords delimiters="braces">
@@ -532,4 +532,26 @@
</cd:keywords>
</cd:define>
+ <!-- * -->
+ <!-- \... {...} -->
+ <!-- -->
+ <!-- * LEFTFENCE -->
+
+ <cd:define name="argument-leftfence">
+ <cd:keywords delimiters="braces">
+ <cd:resolve name="value-leftfence"/>
+ </cd:keywords>
+ </cd:define>
+
+ <!-- * -->
+ <!-- \... {...} -->
+ <!-- -->
+ <!-- * RIGHTFENCE -->
+
+ <cd:define name="argument-rightfence">
+ <cd:keywords delimiters="braces">
+ <cd:resolve name="value-rightfence"/>
+ </cd:keywords>
+ </cd:define>
+
</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-common-instance.xml b/tex/context/interface/mkiv/i-common-instance.xml
index dc8cead79..3d4864de7 100644
--- a/tex/context/interface/mkiv/i-common-instance.xml
+++ b/tex/context/interface/mkiv/i-common-instance.xml
@@ -187,6 +187,7 @@
<cd:define name="instance-mixedcolumns">
<cd:constant value="itemgroupcolumns"/>
<cd:constant value="boxedcolumns"/>
+ <cd:constant value="columns"/>
</cd:define>
<cd:define name="instance-note">
diff --git a/tex/context/interface/mkiv/i-common-string.xml b/tex/context/interface/mkiv/i-common-string.xml
index 5ef1fc71a..0c0bb2ef3 100644
--- a/tex/context/interface/mkiv/i-common-string.xml
+++ b/tex/context/interface/mkiv/i-common-string.xml
@@ -169,4 +169,26 @@
</cd:keywords>
</cd:define>
+ <!-- * -->
+ <!-- \... ... -->
+ <!-- -->
+ <!-- * LEFTFENCE -->
+
+ <cd:define name="string-leftfence">
+ <cd:keywords delimiters="none">
+ <cd:resolve name="value-leftfence"/>
+ </cd:keywords>
+ </cd:define>
+
+ <!-- * -->
+ <!-- \... ... -->
+ <!-- -->
+ <!-- * RIGHTFENCE -->
+
+ <cd:define name="string-rightfence">
+ <cd:keywords delimiters="none">
+ <cd:resolve name="value-rightfence"/>
+ </cd:keywords>
+ </cd:define>
+
</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-common-value.xml b/tex/context/interface/mkiv/i-common-value.xml
index a6884185f..253a03ccf 100644
--- a/tex/context/interface/mkiv/i-common-value.xml
+++ b/tex/context/interface/mkiv/i-common-value.xml
@@ -301,6 +301,17 @@
<cd:constant type="effective"/>
<cd:constant type="header"/>
<cd:constant type="footer"/>
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
</cd:define>
<!-- sortorder = ... -->
@@ -770,4 +781,120 @@
<cd:constant type="cd:name"/>
</cd:define>
+ <cd:define name="value-leftfence">
+ <!--
+ <cd:constant type="||"/>
+ <cd:constant type="|||"/>
+ -->
+ <cd:constant type="\bgroup"/>
+ <cd:constant type="\egroup"/>
+ <cd:constant type="\letteropenbrace"/>
+ <cd:constant type="["/>
+ <cd:constant type="]"/>
+ <cd:constant type="("/>
+ <cd:constant type=")"/>
+ <cd:constant type="<"/>
+ <cd:constant type=">"/>
+ <cd:constant type="/"/>
+ <cd:constant type="|"/>
+ <cd:constant type="⌊"/>
+ <cd:constant type="⌋"/>
+ <cd:constant type="⌈"/>
+ <cd:constant type="⌉"/>
+ <cd:constant type="⟨"/>
+ <cd:constant type="⟩"/>
+ <cd:constant type="⟪"/>
+ <cd:constant type="⟫"/>
+ <cd:constant type="‖"/>
+ <cd:constant type="⦀"/>
+ <cd:constant type="⦗"/>
+ <cd:constant type="\lbrace"/>
+ <cd:constant type="\lbracket"/>
+ <cd:constant type="\lbrack"/>
+ <cd:constant type="\lparenthesis"/>
+ <cd:constant type="\lparent"/>
+ <cd:constant type="\lparen"/>
+ <cd:constant type="\langle"/>
+ <cd:constant type="\llangle"/>
+ <cd:constant type="\lVert"/>
+ <cd:constant type="\vert"/>
+ <cd:constant type="\solidus"/>
+ <cd:constant type="\lfloor"/>
+ <cd:constant type="\lceiling"/>
+ <cd:constant type="\lceil"/>
+ <cd:constant type="\ulcorner"/>
+ <cd:constant type="\llcorner"/>
+ <cd:constant type="\lmoustache"/>
+ <cd:constant type="\llbracket"/>
+ <cd:constant type="\lgroup"/>
+ <cd:constant type="\linterval"/>
+ <cd:constant type="\lointerval"/>
+ <cd:constant type="\llointerval"/>
+ <cd:constant type="\lrointerval"/>
+ <cd:constant type="\{"/>
+ <cd:constant type="\["/>
+ <cd:constant type="\("/>
+ <cd:constant type="\<"/>
+ <cd:constant type="\|"/>
+ <cd:constant type="cd:character"/>
+ </cd:define>
+
+ <cd:define name="value-rightfence">
+ <!--
+ <cd:constant type="||"/>
+ <cd:constant type="|||"/>
+ -->
+ <cd:constant type="\egroup"/>
+ <cd:constant type="\bgroup"/>
+ <cd:constant type="\letterclosebrace"/>
+ <cd:constant type="]"/>
+ <cd:constant type="["/>
+ <cd:constant type=")"/>
+ <cd:constant type="("/>
+ <cd:constant type=">"/>
+ <cd:constant type="<"/>
+ <cd:constant type="/"/>
+ <cd:constant type="|"/>
+ <cd:constant type="⌋"/>
+ <cd:constant type="⌊"/>
+ <cd:constant type="⌉"/>
+ <cd:constant type="⌈"/>
+ <cd:constant type="⟩"/>
+ <cd:constant type="⟨"/>
+ <cd:constant type="⟫"/>
+ <cd:constant type="⟪"/>
+ <cd:constant type="‖"/>
+ <cd:constant type="⦀"/>
+ <cd:constant type="⦘"/>
+ <cd:constant type="\rbrace"/>
+ <cd:constant type="\rbracket"/>
+ <cd:constant type="\rbracket"/>
+ <cd:constant type="\rparenthesis"/>
+ <cd:constant type="\rparent"/>
+ <cd:constant type="\rparen"/>
+ <cd:constant type="\rangle"/>
+ <cd:constant type="\rrangle"/>
+ <cd:constant type="\rVert"/>
+ <cd:constant type="\vert"/>
+ <cd:constant type="\solidus"/>
+ <cd:constant type="\rfloor"/>
+ <cd:constant type="\rceiling"/>
+ <cd:constant type="\rceil"/>
+ <cd:constant type="\urcorner"/>
+ <cd:constant type="\lrcorner"/>
+ <cd:constant type="\rmoustache"/>
+ <cd:constant type="\rrbracket"/>
+ <cd:constant type="\rgroup"/>
+ <cd:constant type="\rinterval"/>
+ <cd:constant type="\rointerval"/>
+ <cd:constant type="\rlointerval"/>
+ <cd:constant type="\rrointerval"/>
+ <cd:constant type="\}"/>
+ <cd:constant type="\]"/>
+ <cd:constant type="\)"/>
+ <cd:constant type="\>"/>
+ <cd:constant type="\|"/>
+ <cd:constant type="cd:character"/>
+ </cd:define>
+
</cd:interface>
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index 237b4ec2b..e1c0e85ae 100644
--- a/tex/context/interface/mkiv/i-context.pdf
+++ b/tex/context/interface/mkiv/i-context.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-context.xml b/tex/context/interface/mkiv/i-context.xml
index 01adac436..53741ad55 100644
--- a/tex/context/interface/mkiv/i-context.xml
+++ b/tex/context/interface/mkiv/i-context.xml
@@ -53,7 +53,6 @@
<cd:interfacefile filename="i-clipping.xml"/>
<cd:interfacefile filename="i-collector.xml"/>
<cd:interfacefile filename="i-color.xml"/>
- <cd:interfacefile filename="i-columns.xml"/>
<cd:interfacefile filename="i-combination.xml"/>
<cd:interfacefile filename="i-commandhandler.xml"/>
<cd:interfacefile filename="i-comment.xml"/>
@@ -198,6 +197,7 @@
<cd:interfacefile filename="i-setups.xml"/>
<cd:interfacefile filename="i-shift.xml"/>
<cd:interfacefile filename="i-sidebar.xml"/>
+ <cd:interfacefile filename="i-simplecolumns.xml"/>
<cd:interfacefile filename="i-smash.xml"/>
<cd:interfacefile filename="i-sort.xml"/>
<cd:interfacefile filename="i-soundtrack.xml"/>
diff --git a/tex/context/interface/mkiv/i-conversion.xml b/tex/context/interface/mkiv/i-conversion.xml
index a2e975368..9226693a2 100644
--- a/tex/context/interface/mkiv/i-conversion.xml
+++ b/tex/context/interface/mkiv/i-conversion.xml
@@ -360,7 +360,7 @@
<cd:command name="date" level="document" category="counter language" file="core-con.mkiv">
<cd:arguments>
- <cd:assignments list="yes" optional="yes">
+ <cd:assignments list="yes">
<cd:parameter name="d">
<cd:constant type="cd:number"/>
</cd:parameter>
@@ -502,6 +502,7 @@
<cd:constant type="set␣2"/>
<cd:constant type="set␣3"/>
<cd:constant type="continued"/>
+ <cd:constant type="zero"/>
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:resolve name="argument-number"/>
@@ -642,4 +643,10 @@
</cd:arguments>
</cd:command>
+ <cd:command name="zeronumberconversion" level="style" category="counter" file="core-con.mkiv">
+ <cd:arguments>
+ <cd:resolve name="argument-number"/>
+ </cd:arguments>
+ </cd:command>
+
</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-direction.xml b/tex/context/interface/mkiv/i-direction.xml
index 3b2d937a4..87e64e457 100644
--- a/tex/context/interface/mkiv/i-direction.xml
+++ b/tex/context/interface/mkiv/i-direction.xml
@@ -52,22 +52,4 @@
<cd:command name="showdirsinmargin" level="document" category="alignment" file="supp-dir.mkiv"/>
- <cd:command name="istltdir" level="system" category="alignment" file="supp-dir.mkiv">
- <cd:arguments>
- <cd:keywords delimiters="none">
- <cd:constant type="TLT"/>
- <cd:constant type="TRT"/>
- </cd:keywords>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="istrtdir" level="system" category="alignment" file="supp-dir.mkiv">
- <cd:arguments>
- <cd:keywords delimiters="none">
- <cd:constant type="TLT"/>
- <cd:constant type="TRT"/>
- </cd:keywords>
- </cd:arguments>
- </cd:command>
-
</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-fittingpage.xml b/tex/context/interface/mkiv/i-fittingpage.xml
index 7fc3a6cff..f5daafcf1 100644
--- a/tex/context/interface/mkiv/i-fittingpage.xml
+++ b/tex/context/interface/mkiv/i-fittingpage.xml
@@ -4,6 +4,30 @@
<cd:interface xmlns:cd="http://www.pragma-ade.com/commands">
+ <cd:define name="assignment-setupfittingpage">
+ <cd:assignments list="yes">
+ <cd:parameter name="pagestate">
+ <cd:constant type="start"/>
+ <cd:constant type="stop" default="yes"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="margin">
+ <cd:constant type="page"/>
+ </cd:parameter>
+ <cd:parameter name="scale">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="paper">
+ <cd:constant type="auto"/>
+ <cd:constant type="default" default="yes"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:inherit name="setupframed"/>
+ </cd:assignments>
+ </cd:define>
+
<cd:command name="definefittingpage" level="style" category="background layout" file="page-app.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name"/>
@@ -17,27 +41,7 @@
<cd:command name="setupfittingpage" level="style" category="background layout" file="page-app.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name-list-optional"/>
- <cd:assignments list="yes">
- <cd:parameter name="pagestate">
- <cd:constant type="start"/>
- <cd:constant type="stop" default="yes"/>
- </cd:parameter>
- <cd:parameter name="command">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="margin">
- <cd:constant type="page"/>
- </cd:parameter>
- <cd:parameter name="scale">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="paper">
- <cd:constant type="auto"/>
- <cd:constant type="default" default="yes"/>
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:inherit name="setupframed"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupfittingpage"/>
</cd:arguments>
</cd:command>
@@ -66,17 +70,17 @@
<!--
- <cd:command name="TEXpage" type="environment" level="document" category="background layout" file="page-app.mkiv">
+ <cd:command name="setupTEXpage" level="style" category="background layout" file="page-app.mkiv">
<cd:arguments>
- <cd:assignments list="yes" optional="yes">
+ <cd:assignments list="yes">
<cd:inherit name="setupfittingpage"/>
</cd:assignments>
</cd:arguments>
</cd:command>
- <cd:command name="MPpage" type="environment" level="document" category="background layout metapost" file="meta-fig.mkiv">
+ <cd:command name="setupMPpage" level="style" category="background layout metapost" file="meta-fig.mkiv">
<cd:arguments>
- <cd:assignments list="yes" optional="yes">
+ <cd:assignments list="yes">
<cd:inherit name="setupfittingpage"/>
</cd:assignments>
</cd:arguments>
@@ -86,17 +90,13 @@
<cd:command name="setupTEXpage" level="style" category="background layout" file="page-app.mkiv">
<cd:arguments>
- <cd:assignments list="yes">
- <cd:inherit name="setupfittingpage"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupfittingpage"/>
</cd:arguments>
</cd:command>
<cd:command name="setupMPpage" level="style" category="background layout metapost" file="meta-fig.mkiv">
<cd:arguments>
- <cd:assignments list="yes">
- <cd:inherit name="setupfittingpage"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupfittingpage"/>
</cd:arguments>
</cd:command>
diff --git a/tex/context/interface/mkiv/i-graphics.xml b/tex/context/interface/mkiv/i-graphics.xml
index a71291a2a..924616474 100644
--- a/tex/context/interface/mkiv/i-graphics.xml
+++ b/tex/context/interface/mkiv/i-graphics.xml
@@ -159,7 +159,7 @@
<cd:constant type="frame"/>
<cd:constant type="empty"/>
</cd:parameter>
- <cd:parameter name="forgroundcolor">
+ <cd:parameter name="foregroundcolor">
<cd:constant type="cd:color"/>
</cd:parameter>
<cd:parameter name="reset">
diff --git a/tex/context/interface/mkiv/i-interactionscreen.xml b/tex/context/interface/mkiv/i-interactionscreen.xml
index 3f23999a3..2f2d550e9 100644
--- a/tex/context/interface/mkiv/i-interactionscreen.xml
+++ b/tex/context/interface/mkiv/i-interactionscreen.xml
@@ -48,6 +48,8 @@
<cd:constant type="attachment"/>
<cd:constant type="layer"/>
<cd:constant type="title"/>
+ <cd:constant type="lefttoright"/>
+ <cd:constant type="righttoleft"/>
<cd:constant type="nomenubar"/>
</cd:parameter>
<cd:parameter name="copies">
diff --git a/tex/context/interface/mkiv/i-itemgroup.xml b/tex/context/interface/mkiv/i-itemgroup.xml
index c27c729f7..416cf1ccd 100644
--- a/tex/context/interface/mkiv/i-itemgroup.xml
+++ b/tex/context/interface/mkiv/i-itemgroup.xml
@@ -4,24 +4,238 @@
<cd:interface xmlns:cd="http://www.pragma-ade.com/commands">
- <cd:command name="defineitemgroup" level="style" category="structure" file="strc-itm.mkvi">
- <cd:arguments>
- <cd:resolve name="keyword-name"/>
- <cd:resolve name="keyword-name-optional"/>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setupitemgroup" level="style" category="structure counter" file="strc-itm.mkvi">
- <cd:arguments>
- <cd:resolve name="keyword-name"/>
- <cd:keywords list="yes" optional="yes">
- <cd:constant type="each"/>
+ <cd:define name="keyword-setupitemgroup">
+ <cd:keywords list="yes" optional="yes">
+ <cd:constant type="intro"/>
+ <cd:constant type="random"/>
+ <cd:constant type="continue"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="autointro"/>
+ <cd:constant type="broad"/>
+ <cd:constant type="text"/>
+ <cd:constant type="before"/>
+ <cd:constant type="after"/>
+ <cd:constant type="nowhite"/>
+ <cd:constant type="margin"/>
+ <cd:constant type="inmargin"/>
+ <cd:constant type="atmargin"/>
+ <cd:constant type="intext"/>
+ <cd:constant type="loose"/>
+ <cd:constant type="fit"/>
+ <cd:constant type="nofit"/>
+ <cd:constant type="paragraph"/>
+ <cd:constant type="joinedup"/>
+ <cd:constant type="serried"/>
+ <cd:constant type="stopper"/>
+ <cd:constant type="nostopper"/>
+ <cd:constant type="unpacked"/>
+ <cd:constant type="repeat"/>
+ <cd:constant type="norepeat"/>
+ <cd:constant type="reverse"/>
+ <cd:constant type="columns"/>
+ <cd:constant type="one"/>
+ <cd:constant type="two"/>
+ <cd:constant type="three"/>
+ <cd:constant type="four"/>
+ <cd:constant type="five"/>
+ <cd:constant type="six"/>
+ <cd:constant type="seven"/>
+ <cd:constant type="eight"/>
+ <cd:constant type="nine"/>
+ <cd:constant type="standard"/>
+ <cd:constant type="broad" prefix="cd:number" method="factor"/>
+ <cd:constant type="serried" prefix="cd:number" method="factor"/>
+ <cd:constant type="horizontal"/>
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
+ </cd:define>
+
+ <cd:define name="assignment-setupitemgroup">
+ <cd:assignments list="yes" optional="yes">
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="inbetween">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="beforehead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="afterhead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="lefttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="righttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="left">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="right">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="factor">
<cd:constant type="cd:number"/>
- </cd:keywords>
- <cd:keywords list="yes" optional="yes">
+ </cd:parameter>
+ <cd:parameter name="step">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="margin">
+ <cd:resolve name="value-leftskip"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargin">
+ <cd:resolve name="value-leftskip"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargin">
+ <cd:resolve name="value-rightskip"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargindistance">
+ <cd:resolve name="value-leftskip"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargindistance">
+ <cd:resolve name="value-rightskip"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="indenting">
+ <cd:inherit name="setupindenting"/>
+ </cd:parameter>
+ <cd:parameter name="start">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="symalign">
+ <cd:constant type="left"/>
+ <cd:constant type="middle"/>
+ <cd:constant type="right"/>
+ <cd:constant type="flushleft"/>
+ <cd:constant type="center"/>
+ <cd:constant type="flushright"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="indentnext">
+ <cd:resolve name="value-indentnext"/>
+ </cd:parameter>
+ <cd:parameter name="inner">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:csname"/>
+ </cd:parameter>
+ <cd:parameter name="items">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="itemalign">
+ <cd:resolve name="value-alignsimple"/>
+ </cd:parameter>
+ <cd:parameter name="alignsymbol">
+ <cd:constant type="yes"/>
+ <cd:constant type="no" default="yes"/>
+ </cd:parameter>
+ <cd:parameter name="textdistance">
+ <cd:constant type="small"/>
+ <cd:constant type="medium"/>
+ <cd:constant type="big"/>
+ <cd:constant type="none"/>
+ <cd:constant type="space" default="yes"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="placestopper">
+ <cd:constant type="yes" default="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="headstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="headcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="marstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="marcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="symstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="symcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="grid">
+ <cd:inherit name="definegridsnapping"/>
+ </cd:parameter>
+ <cd:inherit name="setupcounter"/>
+ </cd:assignments>
+ </cd:define>
+
+ <cd:define name="mixed-setupitemgroup">
+ <cd:assignments list="yes">
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="inbetween">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="beforehead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="afterhead">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="lefttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="righttext">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="left">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="right">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="factor">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="step">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="option">
<cd:constant type="intro"/>
<cd:constant type="random"/>
<cd:constant type="continue"/>
@@ -43,7 +257,6 @@
<cd:constant type="joinedup"/>
<cd:constant type="serried"/>
<cd:constant type="stopper"/>
- <cd:constant type="nostopper"/>
<cd:constant type="unpacked"/>
<cd:constant type="repeat"/>
<cd:constant type="norepeat"/>
@@ -63,334 +276,139 @@
<cd:constant type="serried" prefix="cd:number" method="factor"/>
<cd:constant type="horizontal"/>
<cd:constant type="cd:name"/>
- </cd:keywords>
+ </cd:parameter>
+ <cd:parameter name="margin">
+ <cd:resolve name="value-leftskip"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargin">
+ <cd:resolve name="value-leftskip"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargin">
+ <cd:resolve name="value-rightskip"/>
+ </cd:parameter>
+ <cd:parameter name="leftmargindistance">
+ <cd:resolve name="value-leftskip"/>
+ </cd:parameter>
+ <cd:parameter name="rightmargindistance">
+ <cd:resolve name="value-rightskip"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="indenting">
+ <cd:inherit name="setupindenting"/>
+ </cd:parameter>
+ <cd:parameter name="start">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="symalign">
+ <cd:constant type="left"/>
+ <cd:constant type="middle"/>
+ <cd:constant type="right"/>
+ <cd:constant type="flushleft"/>
+ <cd:constant type="center"/>
+ <cd:constant type="flushright"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="indentnext">
+ <cd:resolve name="value-indentnext"/>
+ </cd:parameter>
+ <cd:parameter name="inner">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:csname"/>
+ </cd:parameter>
+ <cd:parameter name="items">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="itemalign">
+ <cd:resolve name="value-alignsimple"/>
+ </cd:parameter>
+ <cd:parameter name="alignsymbol">
+ <cd:constant type="yes"/>
+ <cd:constant type="no" default="yes"/>
+ </cd:parameter>
+ <cd:parameter name="textdistance">
+ <cd:constant type="small"/>
+ <cd:constant type="medium"/>
+ <cd:constant type="big"/>
+ <cd:constant type="none"/>
+ <cd:constant type="space" default="yes"/>
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="placestopper">
+ <cd:constant type="yes" default="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="headstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="headcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="marstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="marcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="symstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="symcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="grid">
+ <cd:inherit name="definegridsnapping"/>
+ </cd:parameter>
+ <cd:inherit name="setupcounter"/>
+ </cd:assignments>
+ </cd:define>
+
+ <cd:command name="defineitemgroup" level="style" category="structure" file="strc-itm.mkvi">
+ <cd:arguments>
+ <cd:resolve name="keyword-name"/>
+ <cd:resolve name="keyword-name-optional"/>
<cd:assignments list="yes" optional="yes">
- <cd:parameter name="before">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="after">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="inbetween">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="beforehead">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="afterhead">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="lefttext">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="righttext">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="left">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="right">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="factor">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="step">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="width">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="distance">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="margin">
- <cd:resolve name="value-leftskip"/>
- </cd:parameter>
- <cd:parameter name="leftmargin">
- <cd:resolve name="value-leftskip"/>
- </cd:parameter>
- <cd:parameter name="rightmargin">
- <cd:resolve name="value-rightskip"/>
- </cd:parameter>
- <cd:parameter name="leftmargindistance">
- <cd:resolve name="value-leftskip"/>
- </cd:parameter>
- <cd:parameter name="rightmargindistance">
- <cd:resolve name="value-rightskip"/>
- </cd:parameter>
- <cd:parameter name="align">
- <cd:inherit name="setupalign"/>
- </cd:parameter>
- <cd:parameter name="indenting">
- <cd:inherit name="setupindenting"/>
- </cd:parameter>
- <cd:parameter name="start">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="symalign">
- <cd:constant type="left"/>
- <cd:constant type="middle"/>
- <cd:constant type="right"/>
- <cd:constant type="flushleft"/>
- <cd:constant type="center"/>
- <cd:constant type="flushright"/>
- </cd:parameter>
- <cd:parameter name="symbol">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="indentnext">
- <cd:resolve name="value-indentnext"/>
- </cd:parameter>
- <cd:parameter name="inner">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="command">
- <cd:constant type="cd:csname"/>
- </cd:parameter>
- <cd:parameter name="items">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="maxwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="itemalign">
- <cd:resolve name="value-alignsimple"/>
- </cd:parameter>
- <cd:parameter name="alignsymbol">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- </cd:parameter>
- <cd:parameter name="textdistance">
- <cd:constant type="small"/>
- <cd:constant type="medium"/>
- <cd:constant type="big"/>
- <cd:constant type="none"/>
- <cd:constant type="space" default="yes"/>
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="placestopper">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="style">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="color">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="headstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="headcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="marstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="marcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="symstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="symcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="grid">
- <cd:inherit name="definegridsnapping"/>
- </cd:parameter>
- <cd:inherit name="setupcounter"/>
+ <cd:inherit name="setupitemgroup"/>
</cd:assignments>
</cd:arguments>
</cd:command>
+ <cd:command name="setupitemgroup" level="style" category="structure counter" file="strc-itm.mkvi">
+ <cd:arguments>
+ <cd:resolve name="keyword-name"/>
+ <cd:keywords list="yes" optional="yes">
+ <cd:constant type="each"/>
+ <cd:constant type="cd:number"/>
+ </cd:keywords>
+ <cd:resolve name="keyword-setupitemgroup"/>
+ <cd:resolve name="assignment-setupitemgroup"/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="setupitemgroup" variant="assignment" level="style" category="structure counter" file="strc-itm.mkvi">
<cd:arguments>
<cd:keywords list="yes" optional="yes">
<cd:constant type="cd:name"/>
<cd:constant type="cd:number" prefix="cd:name" method="range"/>
</cd:keywords>
- <cd:assignments list="yes">
- <cd:parameter name="before">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="after">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="inbetween">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="beforehead">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="afterhead">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="lefttext">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="righttext">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="left">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="right">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="factor">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="step">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="width">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="distance">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="option">
- <cd:constant type="intro"/>
- <cd:constant type="random"/>
- <cd:constant type="continue"/>
- <cd:constant type="packed"/>
- <cd:constant type="autointro"/>
- <cd:constant type="broad"/>
- <cd:constant type="text"/>
- <cd:constant type="before"/>
- <cd:constant type="after"/>
- <cd:constant type="nowhite"/>
- <cd:constant type="margin"/>
- <cd:constant type="inmargin"/>
- <cd:constant type="atmargin"/>
- <cd:constant type="intext"/>
- <cd:constant type="loose"/>
- <cd:constant type="fit"/>
- <cd:constant type="nofit"/>
- <cd:constant type="paragraph"/>
- <cd:constant type="joinedup"/>
- <cd:constant type="serried"/>
- <cd:constant type="stopper"/>
- <cd:constant type="unpacked"/>
- <cd:constant type="repeat"/>
- <cd:constant type="norepeat"/>
- <cd:constant type="reverse"/>
- <cd:constant type="columns"/>
- <cd:constant type="one"/>
- <cd:constant type="two"/>
- <cd:constant type="three"/>
- <cd:constant type="four"/>
- <cd:constant type="five"/>
- <cd:constant type="six"/>
- <cd:constant type="seven"/>
- <cd:constant type="eight"/>
- <cd:constant type="nine"/>
- <cd:constant type="standard"/>
- <cd:constant type="broad" prefix="cd:number" method="factor"/>
- <cd:constant type="serried" prefix="cd:number" method="factor"/>
- <cd:constant type="horizontal"/>
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="margin">
- <cd:resolve name="value-leftskip"/>
- </cd:parameter>
- <cd:parameter name="leftmargin">
- <cd:resolve name="value-leftskip"/>
- </cd:parameter>
- <cd:parameter name="rightmargin">
- <cd:resolve name="value-rightskip"/>
- </cd:parameter>
- <cd:parameter name="align">
- <cd:inherit name="setupalign"/>
- </cd:parameter>
- <cd:parameter name="indenting">
- <cd:inherit name="setupindenting"/>
- </cd:parameter>
- <cd:parameter name="start">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="symalign">
- <cd:constant type="left"/>
- <cd:constant type="middle"/>
- <cd:constant type="right"/>
- <cd:constant type="flushleft"/>
- <cd:constant type="center"/>
- <cd:constant type="flushright"/>
- </cd:parameter>
- <cd:parameter name="symbol">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="indentnext">
- <cd:resolve name="value-indentnext"/>
- </cd:parameter>
- <cd:parameter name="inner">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="command">
- <cd:constant type="cd:csname"/>
- </cd:parameter>
- <cd:parameter name="items">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="maxwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="itemalign">
- <cd:resolve name="value-alignsimple"/>
- </cd:parameter>
- <cd:parameter name="alignsymbol">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- </cd:parameter>
- <cd:parameter name="textdistance">
- <cd:constant type="small"/>
- <cd:constant type="medium"/>
- <cd:constant type="big"/>
- <cd:constant type="none"/>
- <cd:constant type="space" default="yes"/>
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="placestopper">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="style">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="color">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="headstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="headcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="marstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="marcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="symstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="symcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="grid">
- <cd:inherit name="definegridsnapping"/>
- </cd:parameter>
- <cd:inherit name="setupcounter"/>
- </cd:assignments>
+ <cd:resolve name="mixed-setupitemgroup"/>
</cd:arguments>
</cd:command>
@@ -400,9 +418,7 @@
<cd:constant type="cd:name"/>
<cd:constant type="cd:number" prefix="cd:name" method="range"/>
</cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:assignments>
+ <cd:resolve name="mixed-setupitemgroup"/>
</cd:arguments>
</cd:command>
@@ -416,12 +432,8 @@
<cd:constant type="each"/>
<cd:constant type="cd:number"/>
</cd:keywords>
- <cd:keywords list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:keywords>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:assignments>
+ <cd:resolve name="keyword-setupitemgroup"/>
+ <cd:resolve name="assignment-setupitemgroup"/>
</cd:arguments>
<cd:instances>
<cd:resolve name="instance-itemgroup"/>
@@ -576,34 +588,4 @@
</cd:arguments>
</cd:command>
- <!--
-
- <cd:command name="itemize" type="environment" level="document" category="structure" file="strc-itm.mkvi">
- <cd:arguments>
- <cd:keywords list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:keywords>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setupitemize" level="style" category="structure" file="strc-itm.mkvi">
- <cd:arguments>
- <cd:keywords list="yes" optional="yes">
- <cd:constant type="each"/>
- <cd:constant type="cd:number"/>
- </cd:keywords>
- <cd:keywords list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:keywords>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupitemgroup"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- -->
-
</cd:interface>
diff --git a/tex/context/interface/mkiv/i-math.xml b/tex/context/interface/mkiv/i-math.xml
index ae8fa1c3e..888d2bac5 100644
--- a/tex/context/interface/mkiv/i-math.xml
+++ b/tex/context/interface/mkiv/i-math.xml
@@ -139,6 +139,15 @@
</cd:arguments>
</cd:command>
+ <cd:command name="mathematics" variant="assignment" level="document" category="mathematics" file="math-ini.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setupmathematics"/>
+ </cd:assignments>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="math" level="document" category="mathematics" file="math-ini.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name-optional"/>
@@ -146,6 +155,15 @@
</cd:arguments>
</cd:command>
+ <cd:command name="math" variant="assignment" level="document" category="mathematics" file="math-ini.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setupmathematics"/>
+ </cd:assignments>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="m" level="document" category="mathematics" file="math-ini.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name-optional"/>
@@ -153,6 +171,15 @@
</cd:arguments>
</cd:command>
+ <cd:command name="m" variant="assignment" level="document" category="mathematics" file="math-ini.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setupmathematics"/>
+ </cd:assignments>
+ <cd:content/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="definemathcommand" level="style" category="mathematics" file="math-ini.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name"/>
@@ -310,6 +337,31 @@
</cd:arguments>
</cd:command>
+ <!--
+
+ <cd:command name="text" level="document" category="mathematics" file="math-ini.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:resolve name="argument-text"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="t" level="document" category="mathematics" file="math-ini.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:resolve name="argument-text"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="w" level="document" category="mathematics" file="math-ini.mkiv">
+ <cd:arguments>
+ <cd:resolve name="string-boxoptions"/>
+ <cd:resolve name="argument-text"/>
+ </cd:arguments>
+ </cd:command>
+
+ -->
+
<cd:command name="mathtexttf" level="document" category="mathematics" file="math-ini.mkiv">
<cd:arguments>
<cd:resolve name="string-boxoptions"/>
@@ -511,4 +563,8 @@
</cd:arguments>
</cd:command>
+ <cd:command name="stackscripts" level="document" category="mathematics" file="math-ini.mkiv"/>
+
+ <cd:command name="unstackscripts" level="document" category="mathematics" file="math-ini.mkiv"/>
+
</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-mathfence.xml b/tex/context/interface/mkiv/i-mathfence.xml
index 5e1abec2b..a214c3bfd 100644
--- a/tex/context/interface/mkiv/i-mathfence.xml
+++ b/tex/context/interface/mkiv/i-mathfence.xml
@@ -69,7 +69,48 @@
<cd:command name="fenced" level="document" category="mathematics" file="math-fen.mkiv">
<cd:arguments>
- <cd:resolve name="keyword-name"/>
+ <cd:keywords>
+ <cd:constant type="parenthesis"/>
+ <cd:constant type="bracket"/>
+ <cd:constant type="brace"/>
+ <cd:constant type="bar"/>
+ <cd:constant type="doublebar"/>
+ <cd:constant type="triplebar"/>
+ <cd:constant type="angle"/>
+ <cd:constant type="doubleangle"/>
+ <cd:constant type="solidus"/>
+ <cd:constant type="ceiling"/>
+ <cd:constant type="floor"/>
+ <cd:constant type="moustache"/>
+ <cd:constant type="uppercorner"/>
+ <cd:constant type="lowercorner"/>
+ <cd:constant type="group"/>
+ <cd:constant type="openbracket"/>
+ <!--
+ <cd:constant type="nothing"/>
+ <cd:constant type="mirrored"/>
+ -->
+ <cd:constant type="mirroredparenthesis"/>
+ <cd:constant type="mirroredbracket"/>
+ <cd:constant type="mirroredbrace"/>
+ <cd:constant type="mirroredbar"/>
+ <cd:constant type="mirroreddoublebar"/>
+ <cd:constant type="mirroredtriplebar"/>
+ <cd:constant type="mirroredangle"/>
+ <cd:constant type="mirroreddoubleangle"/>
+ <cd:constant type="mirroredsolidus"/>
+ <cd:constant type="mirroredceiling"/>
+ <cd:constant type="mirroredfloor"/>
+ <cd:constant type="mirroredmoustache"/>
+ <cd:constant type="mirroreduppercorner"/>
+ <cd:constant type="mirroredlowercorner"/>
+ <cd:constant type="mirroredgroup"/>
+ <cd:constant type="mirroredopenbracket"/>
+ <!--
+ <cd:constant type="mirrorednothing"/>
+ -->
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
<cd:content/>
</cd:arguments>
</cd:command>
@@ -78,7 +119,7 @@
<cd:command name="left" level="document" category="mathematics" file="math-fen.mkiv">
<cd:arguments>
- <cd:resolve name="string-character"/>
+ <cd:resolve name="string-leftfence"/>
</cd:arguments>
</cd:command>
@@ -90,7 +131,7 @@
<cd:command name="right" level="document" category="mathematics" file="math-fen.mkiv">
<cd:arguments>
- <cd:resolve name="string-character"/>
+ <cd:resolve name="string-rightfence"/>
</cd:arguments>
</cd:command>
@@ -192,7 +233,7 @@
<cd:command name="lfence" level="document" category="mathematics" file="math-fen.mkiv">
<cd:arguments>
- <cd:resolve name="argument-character"/>
+ <cd:resolve name="argument-leftfence"/>
</cd:arguments>
</cd:command>
@@ -204,7 +245,7 @@
<cd:command name="rfence" level="document" category="mathematics" file="math-fen.mkiv">
<cd:arguments>
- <cd:resolve name="argument-character"/>
+ <cd:resolve name="argument-rightfence"/>
</cd:arguments>
</cd:command>
diff --git a/tex/context/interface/mkiv/i-mixedcolumns.xml b/tex/context/interface/mkiv/i-mixedcolumns.xml
index 4e1ab9625..701375237 100644
--- a/tex/context/interface/mkiv/i-mixedcolumns.xml
+++ b/tex/context/interface/mkiv/i-mixedcolumns.xml
@@ -131,4 +131,12 @@
-->
-</cd:interface> \ No newline at end of file
+ <cd:command name="setupcolumns" level="style" category="structure layout" file="page-smp.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:inherit name="setupmixedcolumns"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+
+</cd:interface>
diff --git a/tex/context/interface/mkiv/i-note.xml b/tex/context/interface/mkiv/i-note.xml
index 03e53a0e3..ee1ac5a31 100644
--- a/tex/context/interface/mkiv/i-note.xml
+++ b/tex/context/interface/mkiv/i-note.xml
@@ -413,6 +413,14 @@
</cd:arguments>
</cd:command>
+ <cd:command name="setupfootnotes" level="style" category="structure notes" file="strc-not.mkvi">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:inherit name="setupnote"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="setnote" level="document" category="structure notes" file="strc-not.mkvi">
<cd:arguments>
<cd:resolve name="keyword-name"/>
@@ -708,4 +716,47 @@
-->
+ <cd:command name="definetextnote" level="style" category="structure notes" file="strc-tnt.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-name"/>
+ <cd:resolve name="keyword-name-optional"/>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setuptextnote"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="setuptextnote" level="style" category="structure notes" file="strc-tnt.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-name-list-optional"/>
+ <cd:assignments list="yes">
+ <cd:parameter name="rule">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="note">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="*"/>
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="empty">
+ <cd:constant type="yes"/>
+ <cd:constant type="no" default="yes"/>
+ <cd:constant type="none"/>
+ <cd:constant type="number"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="textnote" generated="yes" level="document" category="structure notes" file="strc-tnt.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setuptextnote"/>
+ </cd:assignments>
+ <cd:resolve name="argument-text"/>
+ </cd:arguments>
+ </cd:command>
+
</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-pagegrid.xml b/tex/context/interface/mkiv/i-pagegrid.xml
index f25e72f72..8b2cd86b9 100644
--- a/tex/context/interface/mkiv/i-pagegrid.xml
+++ b/tex/context/interface/mkiv/i-pagegrid.xml
@@ -277,7 +277,29 @@
<cd:arguments>
<cd:resolve name="keyword-name"/>
<cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupcolumnsetspan"/>
+ <cd:parameter name="c">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="r">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="method">
+ <cd:constant type="tblr"/>
+ <cd:constant type="lrtb"/>
+ <cd:constant type="tbrl"/>
+ <cd:constant type="rltb"/>
+ <cd:constant type="fxtb"/>
+ <cd:constant type="btlr"/>
+ <cd:constant type="lrbt"/>
+ <cd:constant type="btrl"/>
+ <cd:constant type="rlbt"/>
+ <cd:constant type="fxbt"/>
+ <cd:constant type="fixd"/>
+ </cd:parameter>
+ <cd:parameter name="option">
+ <cd:constant type="none" default="yes"/>
+ <cd:constant type="wide"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
diff --git a/tex/context/interface/mkiv/i-pagenumber.xml b/tex/context/interface/mkiv/i-pagenumber.xml
index 4c262db4b..91c0d8f59 100644
--- a/tex/context/interface/mkiv/i-pagenumber.xml
+++ b/tex/context/interface/mkiv/i-pagenumber.xml
@@ -4,6 +4,22 @@
<cd:interface xmlns:cd="http://www.pragma-ade.com/commands">
+ <cd:define name="assignment-setupuserpagenumber">
+ <cd:assignments list="yes">
+ <cd:parameter name="viewerprefix">
+ <cd:constant type="cd:text"/>
+ </cd:parameter>
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="none"/>
+ <cd:constant type="keep"/>
+ <cd:constant type="empty"/>
+ </cd:parameter>
+ <cd:inherit name="setupcounter"/>
+ </cd:assignments>
+ </cd:define>
+
<cd:command name="setuprealpagenumber" level="system" category="counter" file="strc-pag.mkiv">
<cd:arguments>
<cd:assignments list="yes">
@@ -14,19 +30,7 @@
<cd:command name="setupuserpagenumber" level="style" category="counter" file="strc-pag.mkiv">
<cd:arguments>
- <cd:assignments list="yes">
- <cd:parameter name="viewerprefix">
- <cd:constant type="cd:text"/>
- </cd:parameter>
- <cd:parameter name="state">
- <cd:constant type="start"/>
- <cd:constant type="stop"/>
- <cd:constant type="none"/>
- <cd:constant type="keep"/>
- <cd:constant type="empty"/>
- </cd:parameter>
- <cd:inherit name="setupcounter"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupuserpagenumber"/>
</cd:arguments>
</cd:command>
@@ -40,9 +44,7 @@
<cd:command name="setuppagenumber" level="style" category="counter" file="strc-pag.mkiv">
<cd:arguments>
- <cd:assignments list="yes">
- <cd:inherit name="setupuserpagenumber"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupuserpagenumber"/>
</cd:arguments>
</cd:command>
diff --git a/tex/context/interface/mkiv/i-paragraphs.xml b/tex/context/interface/mkiv/i-paragraphs.xml
index 0d8ae3d2e..e2fc9116e 100644
--- a/tex/context/interface/mkiv/i-paragraphs.xml
+++ b/tex/context/interface/mkiv/i-paragraphs.xml
@@ -79,6 +79,7 @@
<cd:command name="setupparagraphs" variant="assignment" level="style" category="tables" file="tabl-mis.mkiv">
<cd:arguments>
<cd:keywords optional="yes">
+ <cd:constant type="cd:name"/>
<cd:constant type="cd:number" prefix="cd:name" method="range"/>
</cd:keywords>
<cd:assignments list="yes">
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index 3822e876e..9fa13268b 100644
--- a/tex/context/interface/mkiv/i-readme.pdf
+++ b/tex/context/interface/mkiv/i-readme.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-register.xml b/tex/context/interface/mkiv/i-register.xml
index 7ba3a0f7c..e5ddfd821 100644
--- a/tex/context/interface/mkiv/i-register.xml
+++ b/tex/context/interface/mkiv/i-register.xml
@@ -4,6 +4,178 @@
<cd:interface xmlns:cd="http://www.pragma-ade.com/commands">
+ <cd:define name="assignment-setupregister">
+ <cd:assignments list="yes">
+ <cd:parameter name="referencemethod">
+ <cd:constant type="forward"/>
+ </cd:parameter>
+ <cd:parameter name="expansion">
+ <cd:constant type="yes"/>
+ <cd:constant type="no" default="yes"/>
+ <cd:constant type="xml"/>
+ </cd:parameter>
+ <cd:parameter name="ownnumber">
+ <cd:constant type="yes"/>
+ <cd:constant type="no" default="yes"/>
+ </cd:parameter>
+ <cd:parameter name="xmlsetup">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="alternative">
+ <cd:constant type="a"/>
+ <cd:constant type="b"/>
+ <cd:constant type="A"/>
+ <cd:constant type="B"/>
+ </cd:parameter>
+ <cd:parameter name="method">
+ <cd:resolve name="value-sortmethod"/>
+ </cd:parameter>
+ <cd:parameter name="compress">
+ <cd:constant type="yes"/>
+ <cd:constant type="no" default="yes"/>
+ <cd:constant type="all"/>
+ <cd:constant type="packed"/>
+ <cd:constant type="text"/>
+ </cd:parameter>
+ <cd:parameter name="check">
+ <cd:constant type="yes" default="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="criterium">
+ <cd:constant type="local"/>
+ <cd:constant type="text"/>
+ <cd:constant type="current"/>
+ <cd:constant type="previous"/>
+ <cd:constant type="all" default="yes"/>
+ <cd:constant type="cd:section"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixseparatorset">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstarter">
+ <cd:resolve name="value-starter"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixstopper">
+ <cd:resolve name="value-stopper"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixsegments">
+ <cd:resolve name="value-prefixsegments"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefixconnector">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageprefix">
+ <cd:constant type="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="pageseparatorset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pageconversionset">
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="pagestarter">
+ <cd:resolve name="value-starter"/>
+ </cd:parameter>
+ <cd:parameter name="pagestopper">
+ <cd:resolve name="value-stopper"/>
+ </cd:parameter>
+ <cd:parameter name="pagesegments">
+ <cd:resolve name="value-numbersegments"/>
+ </cd:parameter>
+ <cd:parameter name="maxwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="indicator">
+ <cd:constant type="yes" default="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="command">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="textcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="deeptextcommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="pagecommand">
+ <cd:constant type="cd:oneargument"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="interaction">
+ <cd:constant type="text"/>
+ <cd:constant type="pagenumber" default="yes"/>
+ </cd:parameter>
+ <cd:parameter name="pagenumber">
+ <cd:constant type="yes" default="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="symbol">
+ <cd:constant type="a"/>
+ <cd:constant type="n" default="yes"/>
+ <cd:constant type="none"/>
+ <cd:constant type="1"/>
+ <cd:constant type="2"/>
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="language">
+ <cd:resolve name="value-sortorder"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="textstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="textcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pagestyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="pagecolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="pageleft">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="pageright">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="balance">
+ <cd:constant type="yes" default="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="align">
+ <cd:inherit name="setupalign"/>
+ </cd:parameter>
+ <cd:parameter name="numberorder">
+ <cd:constant type="numbers" default="yes"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:define>
+
<cd:command name="defineregister" level="style" category="structure" file="strc-reg.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name"/>
@@ -18,174 +190,7 @@
<cd:arguments>
<cd:resolve name="keyword-name-list-optional"/>
<cd:resolve name="keyword-number-list-optional"/>
- <cd:assignments list="yes">
- <cd:parameter name="referencemethod">
- <cd:constant type="forward"/>
- </cd:parameter>
- <cd:parameter name="expansion">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- <cd:constant type="xml"/>
- </cd:parameter>
- <cd:parameter name="ownnumber">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- </cd:parameter>
- <cd:parameter name="xmlsetup">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="alternative">
- <cd:constant type="a"/>
- <cd:constant type="b"/>
- <cd:constant type="A"/>
- <cd:constant type="B"/>
- </cd:parameter>
- <cd:parameter name="method">
- <cd:resolve name="value-sortmethod"/>
- </cd:parameter>
- <cd:parameter name="compress">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- <cd:constant type="all"/>
- <cd:constant type="packed"/>
- </cd:parameter>
- <cd:parameter name="check">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="criterium">
- <cd:constant type="local"/>
- <cd:constant type="text"/>
- <cd:constant type="current"/>
- <cd:constant type="previous"/>
- <cd:constant type="all" default="yes"/>
- <cd:constant type="cd:section"/>
- </cd:parameter>
- <cd:parameter name="pageprefixseparatorset">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="pageprefixconversionset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pageprefixstarter">
- <cd:resolve name="value-starter"/>
- </cd:parameter>
- <cd:parameter name="pageprefixstopper">
- <cd:resolve name="value-stopper"/>
- </cd:parameter>
- <cd:parameter name="pageprefixset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pageprefixsegments">
- <cd:resolve name="value-prefixsegments"/>
- </cd:parameter>
- <cd:parameter name="pageprefixconnector">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="pageprefix">
- <cd:constant type="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="pageseparatorset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pageconversionset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pagestarter">
- <cd:resolve name="value-starter"/>
- </cd:parameter>
- <cd:parameter name="pagestopper">
- <cd:resolve name="value-stopper"/>
- </cd:parameter>
- <cd:parameter name="pagesegments">
- <cd:resolve name="value-numbersegments"/>
- </cd:parameter>
- <cd:parameter name="maxwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="indicator">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="before">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="after">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="command">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="textcommand">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="deeptextcommand">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="pagecommand">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="distance">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="interaction">
- <cd:constant type="text"/>
- <cd:constant type="pagenumber" default="yes"/>
- </cd:parameter>
- <cd:parameter name="pagenumber">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="symbol">
- <cd:constant type="a"/>
- <cd:constant type="n" default="yes"/>
- <cd:constant type="none"/>
- <cd:constant type="1"/>
- <cd:constant type="2"/>
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="language">
- <cd:resolve name="value-sortorder"/>
- </cd:parameter>
- <cd:parameter name="style">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="color">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="textstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="textcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="pagestyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="pagecolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="pageleft">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="pageright">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="balance">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="align">
- <cd:inherit name="setupalign"/>
- </cd:parameter>
- <cd:parameter name="numberorder">
- <cd:constant type="numbers" default="yes"/>
- </cd:parameter>
- </cd:assignments>
+ <cd:resolve name="assignment-setupregister"/>
</cd:arguments>
</cd:command>
@@ -195,173 +200,7 @@
<cd:constant type="cd:name"/>
<cd:constant type="cd:number" prefix="cd:name" method="range"/>
</cd:keywords>
- <cd:assignments list="yes">
- <cd:parameter name="referencemethod">
- <cd:constant type="forward"/>
- </cd:parameter>
- <cd:parameter name="expansion">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- <cd:constant type="xml"/>
- </cd:parameter>
- <cd:parameter name="ownnumber">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- </cd:parameter>
- <cd:parameter name="xmlsetup">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="alternative">
- <cd:constant type="a"/>
- <cd:constant type="b"/>
- <cd:constant type="A"/>
- <cd:constant type="B"/>
- </cd:parameter>
- <cd:parameter name="method">
- <cd:resolve name="value-sortmethod"/>
- </cd:parameter>
- <cd:parameter name="compress">
- <cd:constant type="yes"/>
- <cd:constant type="no" default="yes"/>
- <cd:constant type="all"/>
- </cd:parameter>
- <cd:parameter name="check">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="criterium">
- <cd:constant type="local"/>
- <cd:constant type="text"/>
- <cd:constant type="current"/>
- <cd:constant type="previous"/>
- <cd:constant type="all" default="yes"/>
- <cd:constant type="cd:section"/>
- </cd:parameter>
- <cd:parameter name="pageprefixseparatorset">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="pageprefixconversionset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pageprefixstarter">
- <cd:resolve name="value-starter"/>
- </cd:parameter>
- <cd:parameter name="pageprefixstopper">
- <cd:resolve name="value-stopper"/>
- </cd:parameter>
- <cd:parameter name="pageprefixset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pageprefixsegments">
- <cd:resolve name="value-prefixsegments"/>
- </cd:parameter>
- <cd:parameter name="pageprefixconnector">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="pageprefix">
- <cd:constant type="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="pageseparatorset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pageconversionset">
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="pagestarter">
- <cd:resolve name="value-starter"/>
- </cd:parameter>
- <cd:parameter name="pagestopper">
- <cd:resolve name="value-stopper"/>
- </cd:parameter>
- <cd:parameter name="pagesegments">
- <cd:resolve name="value-numbersegments"/>
- </cd:parameter>
- <cd:parameter name="maxwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="indicator">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="before">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="after">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="command">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="textcommand">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="deeptextcommand">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="pagecommand">
- <cd:constant type="cd:oneargument"/>
- </cd:parameter>
- <cd:parameter name="distance">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="interaction">
- <cd:constant type="text"/>
- <cd:constant type="pagenumber" default="yes"/>
- </cd:parameter>
- <cd:parameter name="pagenumber">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="symbol">
- <cd:constant type="a"/>
- <cd:constant type="n" default="yes"/>
- <cd:constant type="none"/>
- <cd:constant type="1"/>
- <cd:constant type="2"/>
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="language">
- <cd:resolve name="value-sortorder"/>
- </cd:parameter>
- <cd:parameter name="style">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="color">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="textstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="textcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="pagestyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="pagecolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="pageleft">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="pageright">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="balance">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="align">
- <cd:inherit name="setupalign"/>
- </cd:parameter>
- <cd:parameter name="numberorder">
- <cd:constant type="numbers" default="yes"/>
- </cd:parameter>
- </cd:assignments>
+ <cd:resolve name="assignment-setupregister"/>
</cd:arguments>
</cd:command>
@@ -369,9 +208,7 @@
<cd:arguments>
<cd:resolve name="keyword-name-list-optional"/>
<cd:resolve name="keyword-number-list-optional"/>
- <cd:assignments list="yes">
- <cd:inherit name="setupregister"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupregister"/>
</cd:arguments>
</cd:command>
@@ -381,9 +218,7 @@
<cd:constant type="cd:name"/>
<cd:constant type="cd:number" prefix="cd:name" method="range"/>
</cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setupregister"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupregister"/>
</cd:arguments>
</cd:command>
@@ -478,9 +313,7 @@
</cd:sequence>
<cd:arguments>
<cd:resolve name="keyword-number-list-optional"/>
- <cd:assignments list="yes">
- <cd:inherit name="setupregister"/>
- </cd:assignments>
+ <cd:resolve name="assignment-setupregister"/>
</cd:arguments>
<cd:instances>
<cd:resolve name="instance-register"/>
@@ -489,63 +322,25 @@
<!--
- <cd:command name="index" level="document" category="structure" file="strc-reg.mkiv">
+ <cd:command name="startregister" level="document" category="structure" file="strc-reg.mkiv">
<cd:arguments>
+ <cd:resolve name="keyword-name"/>
+ <cd:resolve name="keyword-name"/>
<cd:keywords optional="yes">
<cd:constant type="cd:text"/>
- <cd:constant type="cd:text" prefix="cd:processor" method="apply"/>
</cd:keywords>
- <cd:index list="yes"/>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="index" variant="ownnumber" level="document" category="structure" file="strc-reg.mkiv">
- <cd:arguments>
<cd:keywords optional="yes">
<cd:constant type="cd:text"/>
<cd:constant type="cd:text" prefix="cd:processor" method="apply"/>
</cd:keywords>
- <cd:resolve name="argument-text"/>
<cd:index list="yes"/>
</cd:arguments>
</cd:command>
- <cd:command name="seeindex" level="document" category="structure" file="strc-reg.mkiv">
- <cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="cd:text"/>
- <cd:constant type="cd:text" prefix="cd:processor" method="apply"/>
- </cd:keywords>
- <cd:index list="yes"/>
- <cd:keywords delimiters="braces">
- <cd:constant type="cd:text"/>
- <cd:constant type="cd:text" prefix="cd:processor" method="apply"/>
- </cd:keywords>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="placeindex" level="document" category="structure" file="strc-reg.mkiv">
- <cd:arguments>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupregister"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="completeindex" level="document" category="structure" file="strc-reg.mkiv">
- <cd:arguments>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setupregister"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setupindex" level="style" category="structure" file="strc-reg.mkiv">
+ <cd:command name="stopregister" level="document" category="structure" file="strc-reg.mkiv">
<cd:arguments>
- <cd:resolve name="keyword-number-list-optional"/>
- <cd:assignments list="yes">
- <cd:inherit name="setupregister"/>
- </cd:assignments>
+ <cd:resolve name="keyword-name"/>
+ <cd:resolve name="keyword-name"/>
</cd:arguments>
</cd:command>
@@ -563,11 +358,8 @@
<cd:constant type="cd:text" prefix="cd:processor" method="apply"/>
</cd:keywords>
<cd:index list="yes"/>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="stopregister" level="document" category="structure" file="strc-reg.mkiv">
- <cd:arguments>
+ <cd:resolve name="string-content"/>
+ <cd:delimiter name="stopregister"/>
<cd:resolve name="keyword-name"/>
<cd:resolve name="keyword-name"/>
</cd:arguments>
@@ -612,17 +404,34 @@
</cd:arguments>
</cd:command>
+ <!--
+
+ <cd:command name="startstructurepageregister" level="document" category="structure" file="strc-reg.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-name"/>
+ <cd:resolve name="keyword-name"/>
+ <cd:resolve name="assignment-registerdata-list"/>
+ <cd:resolve name="assignment-userdata-list-optional"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="stopstructurepageregister" level="document" category="structure" file="strc-reg.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-name"/>
+ <cd:resolve name="keyword-name"/>
+ </cd:arguments>
+ </cd:command>
+
+ -->
+
<cd:command name="startstructurepageregister" level="document" category="structure" file="strc-reg.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name"/>
<cd:resolve name="keyword-name"/>
<cd:resolve name="assignment-registerdata-list"/>
<cd:resolve name="assignment-userdata-list-optional"/>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="stopstructurepageregister" level="document" category="structure" file="strc-reg.mkiv">
- <cd:arguments>
+ <cd:resolve name="string-content"/>
+ <cd:delimiter name="stopstructurepageregister"/>
<cd:resolve name="keyword-name"/>
<cd:resolve name="keyword-name"/>
</cd:arguments>
diff --git a/tex/context/interface/mkiv/i-section.xml b/tex/context/interface/mkiv/i-section.xml
index b4229d5fd..0ec20a804 100644
--- a/tex/context/interface/mkiv/i-section.xml
+++ b/tex/context/interface/mkiv/i-section.xml
@@ -246,6 +246,10 @@
<cd:constant type="positive"/>
<cd:constant type="all"/>
</cd:parameter>
+ <cd:parameter name="hidenumber">
+ <cd:constant type="yes"/>
+ <cd:constant type="no" default="yes"/>
+ </cd:parameter>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -319,6 +323,30 @@
</cd:arguments>
</cd:command>
+ <cd:command name="placerawheaddata" level="system" category="structure" file="strc-sec.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-section"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="placerawheadtext" level="system" category="structure" file="strc-sec.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-section"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="placerawheadnumber" level="system" category="structure" file="strc-sec.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-section"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="repeathead" level="document" category="structure" file="strc-sec.mkiv">
+ <cd:arguments>
+ <cd:resolve name="keyword-section"/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="definesection" level="system" category="structure" file="strc-sec.mkiv">
<cd:arguments>
<cd:resolve name="keyword-name"/>
diff --git a/tex/context/interface/mkiv/i-simplecolumns.xml b/tex/context/interface/mkiv/i-simplecolumns.xml
new file mode 100644
index 000000000..caefa9fbb
--- /dev/null
+++ b/tex/context/interface/mkiv/i-simplecolumns.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?context-directive job ctxfile x-setups.ctx ?>
+
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands">
+
+ <cd:command name="setsimplecolumnshsize" level="system" category="structure layout" file="page-smp.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="distance">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="lines">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="simplecolumns" type="environment" level="system" category="structure layout" file="page-smp.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes" optional="yes">
+ <cd:inherit name="setsimplecolumnshsize"/>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+
+</cd:interface> \ No newline at end of file
diff --git a/tex/context/interface/mkiv/i-symbol.xml b/tex/context/interface/mkiv/i-symbol.xml
index 498684cad..64a6f27dd 100644
--- a/tex/context/interface/mkiv/i-symbol.xml
+++ b/tex/context/interface/mkiv/i-symbol.xml
@@ -147,4 +147,15 @@
</cd:arguments>
</cd:command>
-</cd:interface> \ No newline at end of file
+ <cd:command name="setupsymbols" level="style" category="symbols" file="symb-ini.mkiv">
+ <cd:arguments>
+ <cd:assignments list="yes">
+ <cd:parameter name="stylealternative">
+ <cd:constant type="text" default="yes"/>
+ <cd:constant type="math"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:arguments>
+ </cd:command>
+
+</cd:interface>
diff --git a/tex/context/interface/mkiv/i-texts.xml b/tex/context/interface/mkiv/i-texts.xml
index f0f515fbc..f13d88021 100644
--- a/tex/context/interface/mkiv/i-texts.xml
+++ b/tex/context/interface/mkiv/i-texts.xml
@@ -4,97 +4,68 @@
<cd:interface xmlns:cd="http://www.pragma-ade.com/commands">
- <!--
-
- <cd:command name="definelayoutelement" level="system" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:resolve name="keyword-name"/>
- <cd:resolve name="keyword-name-optional"/>
- <cd:assignments list="yes" optional="yes">
- <cd:inherit name="setuplayoutelement"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setuplayoutelement" level="system" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:resolve name="keyword-name-list-optional"/>
- <cd:assignments list="yes">
- <cd:parameter name="state">
- <cd:constant type="start"/>
- <cd:constant type="stop"/>
- <cd:constant type="empty"/>
- <cd:constant type="high"/>
- <cd:constant type="none"/>
- <cd:constant type="normal" default="yes"/>
- <cd:constant type="nomarking"/>
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="style">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="color">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="strut">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="before">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="after">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="leftstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="rightstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="leftcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="rightcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="width">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="leftwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="rightwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setuplayouttext" level="system" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:keywords>
- <cd:constant type="top"/>
- <cd:constant type="header"/>
- <cd:constant type="text"/>
- <cd:constant type="footer"/>
- <cd:constant type="bottom"/>
- </cd:keywords>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayoutelement"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- -->
+ <cd:define name="keyword-setuplayouttext">
+ <cd:keywords optional="yes">
+ <cd:constant type="text"/>
+ <cd:constant type="margin"/>
+ <cd:constant type="edge"/>
+ </cd:keywords>
+ </cd:define>
+
+ <cd:define name="assignment-setuplayouttext">
+ <cd:assignments list="yes">
+ <cd:parameter name="state">
+ <cd:constant type="start"/>
+ <cd:constant type="stop"/>
+ <cd:constant type="empty"/>
+ <cd:constant type="high"/>
+ <cd:constant type="none"/>
+ <cd:constant type="normal" default="yes"/>
+ <cd:constant type="nomarking"/>
+ <cd:constant type="cd:name"/>
+ </cd:parameter>
+ <cd:parameter name="style">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="color">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="strut">
+ <cd:constant type="yes" default="yes"/>
+ <cd:constant type="no"/>
+ </cd:parameter>
+ <cd:parameter name="n">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="before">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="after">
+ <cd:constant type="cd:command"/>
+ </cd:parameter>
+ <cd:parameter name="leftstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="rightstyle">
+ <cd:resolve name="value-style"/>
+ </cd:parameter>
+ <cd:parameter name="leftcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="rightcolor">
+ <cd:constant type="cd:color"/>
+ </cd:parameter>
+ <cd:parameter name="width">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="leftwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ <cd:parameter name="rightwidth">
+ <cd:constant type="cd:dimension"/>
+ </cd:parameter>
+ </cd:assignments>
+ </cd:define>
<cd:command name="setuplayouttext" level="style" category="layout" file="page-txt.mkvi">
<cd:arguments>
@@ -105,197 +76,43 @@
<cd:constant type="footer"/>
<cd:constant type="bottom"/>
</cd:keywords>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:parameter name="state">
- <cd:constant type="start"/>
- <cd:constant type="stop"/>
- <cd:constant type="empty"/>
- <cd:constant type="high"/>
- <cd:constant type="none"/>
- <cd:constant type="normal" default="yes"/>
- <cd:constant type="nomarking"/>
- <cd:constant type="cd:name"/>
- </cd:parameter>
- <cd:parameter name="style">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="color">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="strut">
- <cd:constant type="yes" default="yes"/>
- <cd:constant type="no"/>
- </cd:parameter>
- <cd:parameter name="n">
- <cd:constant type="cd:number"/>
- </cd:parameter>
- <cd:parameter name="before">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="after">
- <cd:constant type="cd:command"/>
- </cd:parameter>
- <cd:parameter name="leftstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="rightstyle">
- <cd:resolve name="value-style"/>
- </cd:parameter>
- <cd:parameter name="leftcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="rightcolor">
- <cd:constant type="cd:color"/>
- </cd:parameter>
- <cd:parameter name="width">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="leftwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- <cd:parameter name="rightwidth">
- <cd:constant type="cd:dimension"/>
- </cd:parameter>
- </cd:assignments>
+ <cd:resolve name="keyword-setuplayouttext"/>
+ <cd:resolve name="assignment-setuplayouttext"/>
</cd:arguments>
</cd:command>
- <!--
-
- <cd:command name="setuptop" level="style" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayoutelement"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setupheader" level="style" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayoutelement"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setuptext" level="style" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayoutelement"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setupfooter" level="style" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayoutelement"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- <cd:command name="setupbottom" level="style" category="layout" file="page-txt.mkvi">
- <cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayoutelement"/>
- </cd:assignments>
- </cd:arguments>
- </cd:command>
-
- -->
-
<cd:command name="setuptop" level="style" category="layout" file="page-txt.mkvi">
<cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
- </cd:assignments>
+ <cd:resolve name="keyword-setuplayouttext"/>
+ <cd:resolve name="assignment-setuplayouttext"/>
</cd:arguments>
</cd:command>
<cd:command name="setupheader" level="style" category="layout" file="page-txt.mkvi">
<cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
- </cd:assignments>
+ <cd:resolve name="keyword-setuplayouttext"/>
+ <cd:resolve name="assignment-setuplayouttext"/>
</cd:arguments>
</cd:command>
<cd:command name="setuptext" level="style" category="layout" file="page-txt.mkvi">
<cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
- </cd:assignments>
+ <cd:resolve name="keyword-setuplayouttext"/>
+ <cd:resolve name="assignment-setuplayouttext"/>
</cd:arguments>
</cd:command>
<cd:command name="setupfooter" level="style" category="layout" file="page-txt.mkvi">
<cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
- </cd:assignments>
+ <cd:resolve name="keyword-setuplayouttext"/>
+ <cd:resolve name="assignment-setuplayouttext"/>
</cd:arguments>
</cd:command>
<cd:command name="setupbottom" level="style" category="layout" file="page-txt.mkvi">
<cd:arguments>
- <cd:keywords optional="yes">
- <cd:constant type="text"/>
- <cd:constant type="margin"/>
- <cd:constant type="edge"/>
- </cd:keywords>
- <cd:assignments list="yes">
- <cd:inherit name="setuplayouttext"/>
- </cd:assignments>
+ <cd:resolve name="keyword-setuplayouttext"/>
+ <cd:resolve name="assignment-setuplayouttext"/>
</cd:arguments>
</cd:command>
diff --git a/tex/context/interface/mkiv/i-vspace.xml b/tex/context/interface/mkiv/i-vspace.xml
index 5e970d317..e79e4e736 100644
--- a/tex/context/interface/mkiv/i-vspace.xml
+++ b/tex/context/interface/mkiv/i-vspace.xml
@@ -140,4 +140,10 @@
</cd:arguments>
</cd:command>
+ <cd:command name="crlf" level="document" category="whitespace" file="typo-wrp.mkiv"/>
+
+ <cd:command name="settestcrlf" level="document" category="whitespace" file="typo-wrp.mkiv"/>
+
+ <cd:command name="crlfplaceholder" level="document" category="whitespace" file="typo-wrp.mkiv"/>
+
</cd:interface>
diff --git a/tex/context/modules/mkiv/m-scite.mkiv b/tex/context/modules/mkiv/m-scite.mkiv
index 9182fa2ec..4fb7ea029 100644
--- a/tex/context/modules/mkiv/m-scite.mkiv
+++ b/tex/context/modules/mkiv/m-scite.mkiv
@@ -289,6 +289,7 @@ visualizers.register("cld", visualizer)
visualizers.register("tex", visualizer)
visualizers.register("lua", visualizer)
visualizers.register("mps", visualizer)
+visualizers.register("mp", visualizer)
visualizers.register("pdf", visualizer)
visualizers.register("xml", visualizer)
visualizers.register("bibtex",visualizer)
@@ -306,7 +307,7 @@ visualizers.register("json", visualizer)
\definetyping[LUA] [option=lua]
\definetyping[BTX] [option=bibtex]
\definetyping[MPS] [option=mps]
-\definetyping[MP] [option=mps]
+\definetyping[MP] [option=mp]
\definetyping[PDF] [option=pdf]
\definetyping[CPP] [option=web]
\definetyping[WEB] [option=web]
diff --git a/tex/context/modules/mkiv/s-fonts-system.lua b/tex/context/modules/mkiv/s-fonts-system.lua
index dc0f2e6a3..8e55184e0 100644
--- a/tex/context/modules/mkiv/s-fonts-system.lua
+++ b/tex/context/modules/mkiv/s-fonts-system.lua
@@ -123,7 +123,7 @@ function moduledata.fonts.system.showinstalledglyphnames(specification)
local names = table.setmetatableindex("table")
local f_u = formatters["%04X"]
for i=1,#paths do
- local list = dir.glob(paths[i].."/fonts/o*/**.tmc")
+ local list = dir.glob(paths[i].."/fonts/o*/**." .. utilities.lua.suffixes.tmc)
for i=1,#list do
files[list[i]] = true
end
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 65c823a66..c43b1d8da 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 : 07/24/19 11:17:48
+-- merge date : 07/31/19 18:05:38
do -- begin closure to overcome local limits and interference
@@ -3396,6 +3396,13 @@ local template=[[
%s
return function(%s) return %s end
]]
+local pattern=Cs(Cc('"')*(
+ (1-S('"\\\n\r'))^1+P('"')/'\\"'+P('\\')/'\\\\'+P('\n')/'\\n'+P('\r')/'\\r'
+)^0*Cc('"'))
+patterns.escapedquotes=pattern
+function string.escapedquotes(s)
+ return lpegmatch(pattern,s)
+end
local preamble=""
local environment={
global=global or _G,
@@ -3422,6 +3429,7 @@ local environment={
formattedfloat=number.formattedfloat,
stripzero=patterns.stripzero,
stripzeros=patterns.stripzeros,
+ escapedquotes=string.escapedquotes,
FORMAT=string.f9,
}
local arguments={ "a1" }
@@ -3479,7 +3487,7 @@ local format_q=function()
end
local format_Q=function()
n=n+1
- return format("format('%%q',tostring(a%s))",n)
+ return format("escapedquotes(tostring(a%s))",n)
end
local format_i=function(f)
n=n+1
@@ -11502,7 +11510,7 @@ readers.vmtx=function(f,fontdata,specification)
local topsidebearing=0
for i=0,nofmetrics-1 do
local glyph=glyphs[i]
- vheight=readshort(f)
+ vheight=readushort(f)
topsidebearing=readshort(f)
if vheight~=0 and vheight~=vdefault then
glyph.vheight=vheight
@@ -11587,9 +11595,12 @@ local sequence={
{ 3,1,4 },
{ 3,10,12 },
{ 0,3,4 },
+ { 0,3,12 },
{ 0,1,4 },
+ { 0,1,12 },
{ 0,0,6 },
{ 3,0,6 },
+ { 3,0,4 },
{ 0,5,14 },
{ 0,4,12 },
{ 3,10,13 },
@@ -11859,24 +11870,33 @@ formatreaders[14]=function(f,fontdata,offset)
end
end
local function checkcmap(f,fontdata,records,platform,encoding,format)
- local data=records[platform]
- if not data then
+ local pdata=records[platform]
+ if not pdata then
if trace_cmap_details then
report_cmap("skipped, %s, p=%i e=%i f=%i","no platform",platform,encoding,format)
end
return 0
end
- data=data[encoding]
- if not data then
+ local edata=pdata[encoding]
+ if not edata then
if trace_cmap_details then
report_cmap("skipped, %s, p=%i e=%i f=%i","no encoding",platform,encoding,format)
end
return 0
end
- data=data[format]
- if not data then
+ local fdata=edata[format]
+ if not fdata then
+ if trace_cmap_details then
+ report_cmap("skipped, %s, p=%i e=%i f=%i","no format",platform,encoding,format)
+ end
+ return 0
+ elseif type(fdata)~="number" then
+ if trace_cmap_details then
+ report_cmap("skipped, %s, p=%i e=%i f=%i","already done",platform,encoding,format)
+ end
return 0
end
+ edata[format]=true
local reader=formatreaders[format]
if not reader then
if trace_cmap_details then
@@ -11884,8 +11904,8 @@ local function checkcmap(f,fontdata,records,platform,encoding,format)
end
return 0
end
- local n=reader(f,fontdata,data) or 0
- if trace_cmap then
+ local n=reader(f,fontdata,fdata) or 0
+ if trace_cmap_details or trace_cmap then
local p=platforms[platform]
local e=encodings[p]
report_cmap("checked, platform %i (%s), encoding %i (%s), format %i, new unicodes %i",